一、搜索引擎营销
搜索引擎营销,简称SEM,是网络营销的一种。就是根据用户使用搜索引擎的方式,利用用户检索信息的机会通过搜索引擎返回的结果,尽可能将营销信息传递给目标用户,以此来获得更好的销售或者推广效果。
二、病毒性营销
病毒性营销也被人们称为病毒式营销和病毒营销。病毒性营销是一种常用的网络营销方法,常用于进行网站推广、品牌推广等,病毒性营销利用的是用户口碑传播的原理。
三、电子邮件营销
电子邮件营销(邮件营销)是利用电子邮件与受众客户进行商业交流的一种直销方式。同时也广泛的应用于网络营销领域。
四、电话营销
电话营销(TMK)的定义为:通过使用电话,来实现有计划、有组织并且高效率地扩大顾客群、提高顾客满意度、维护老顾客等市场行为的手法。
五、论坛营销
论坛营销就是“企业利用论坛这种网络交流的平台,通过文字、图片、视频等方式发布企业的产品和服务的信息,从而让目标客户更加深刻地了解企业的产品和服务。最终达到企业宣传企业的品牌、加深市场认知度的网络营销活动”,就是论坛营销。
参考资料来源:百度百科-营销
虽然不是C#,但意思如下,希望能帮到你。。。。。这是我自己以前做过的。
#include <stdio.h>
struct{
char pstatus //哲学家状态
int pid//哲学家编号
int waiter1
int priority//优先级,数值大的就餐的优先级高
}pcb[6]
struct sp{
int stick //筷子状态,0表示可使用或表示空闲,1表示有人在使用或不空闲
}num[6]//筷子编号
struct{
int value //互斥信号量,临界区数,初值为1
int waiter2 //同步信号量,初值为0
}sem[5]
char stack[11][6]
int m1,m2//为系统设置的公用数据被三个进程共享使用。
int i,ep //ep表示正在就餐的哲学家的pid,i为通用寄存器
char addr //addr为程序计数器
void init()//初始化函数
int find()//查找
int hungry()
int process1()
int process2()
int process3()
int process4()
int process5()
int p(int,int ,char)
int v(int,int ,char)
int main(){
init()
printf("系统程序开始执行\n")
for()
{ if( find()!=0 ) hungry()
else break
}
printf("系统程序结束\n")
}
void init(){
int j,k
pcb[0].pstatus='w'
pcb[0].priority=2//数越大优先级越高
for( j=1j<=5j++)
{
num[j].stick=0
pcb[j].pid=j
pcb[j].pstatus='t'
pcb[j].priority=5
}
for(j=1j<=5j++)
{
sem[j].value=1
sem[j].waiter2=0
}
i=0ep=0m1=0 m2=0
for(j=1j<=11j++)
{
for(k=1k<=6k++)
stack[j][k]='0'
}
}
int find()
{
int j
for(j=1j<=5j++)
if(pcb[j].pstatus=='t'&&pcb[j].priority==5)return (j)
return 0
}
int hungry(){
int j,left,right
j=find()
left=j
right=j+1
if(j==0) return(0)
/*else if(num[left].stick==1||num[right].stick==1){
num[left].stick=0
num[right].stick=0
pcb[j].pstatus='w'
printf("在等吃饭的哲学家编号为%d\n",pcb[j].pid)}*/
if(ep==0){
//&&num[left].stick==0 &&num[right].stick==0&&pcb[j].pstatus=='t'&&pcb[j].priority==5
if(num[left].stick==0&&num[right].stick==0)
{
printf("将正在思考的哲学家%d状态设为执行状态\n",pcb[j].pid)
printf("读取进程%d\n",pcb[j].pid)
pcb[j].pstatus='e'
ep=j
num[left].stick=1
num[right].stick=1
printf("运行进程%d\n",ep)
pcb[ep].priority--
}
else{
printf("哲学家%d没有同时获得左右两只筷子,只好放下筷子等待吃饭\n",pcb[j].pid)
num[left].stick=0
num[right].stick=0
pcb[j].pstatus='w'
pcb[j].priority++
if(pcb[j].pstatus=='w'&&pcb[j].priority>pcb[j-1].priority)
{ printf("将在等待中哲学家%d设为t状态\n",pcb[j].pid)
pcb[j].pstatus='t'
printf("读取进程%d\n",pcb[j].pid)
pcb[j].pstatus='e'
ep=j}
}
}
i=stack[1][ep]
addr=stack[2][ep]
switch(ep){
case 1:process1()
break
case 2:process2()
break
case 3:process3()
break
case 4:process4()
break
case 5:process5()
break
default:printf("当前进程出错!%d\n",ep)
break
}
}
process1(){
if(addr=='m') goto m
i=1
a:
printf("哲学家1在信号量sem[1]上调用P操作\n")
if(p(1,1,'m')==0) return(0)
else goto m
m:
printf("打印进程1...m1=%d\n",m1)
printf("打印进程1...i=%d\n",i)
i+=5
goto a
}
process2(){
if(addr=='m') goto m
if(addr=='n') goto n
i=1
a:
printf("进程2在信号量sem[3]上调用P操作\n")
if(p(3,2,'m')==0) return(0)
m:
m1=m2+4
printf("进程2在信号量sem[2]上调用V操作m1=%d\n",m1)
if(v(2,2,'n')==0) return(0)
else{
n:
printf("打印进程2...i=%d\n",i)
i+=10
goto a
}
}
process3(){
if(addr=='m') goto m
if(addr=='n') goto n
i=1
a:
printf("进程3在信号量sem[4]上调用P操作\n")
if(p(4,3,'m')==0) return(0)
m:
m1=m2+4
printf("进程3在信号量sem[2]上调用V操作m1=%d\n",m1)
if(v(2,3,'n')==0) return(0)
else{
n:
printf("打印进程3...i=%d\n",i)
i+=15
goto a
}
}
process4(){
if(addr=='m') goto m
if(addr=='n') goto n
i=1
a:
printf("进程4在信号量sem[4]上调用P操作\n")
if(p(4,4,'m')==0) return(0)
m:
m1=m2+4
printf("进程4在信号量sem[3]上调用V操作m1=%d\n",m1)
if(v(3,4,'n')==0) return(0)
else{
n:
printf("打印进程4...i=%d\n",i)
i+=20
goto a
}
}
process5(){
if(addr=='m') goto m
if(addr=='n') goto n
i=1
a:
if(i>1){
printf("进程5在信号量sem[2]上调用P操作\n")
if(p(2,5,'n')==0) return(0)
}
n:
m2=i
printf("进程5在sem[5]信号量上调用V操作m=%d\n",m2)
if(v(5,5,'m')==0) return(0)
else{
m:
i+=1
goto a
}
}
int p(int se,int p,char ad){ //p操作
int w //等待指示字单元
sem[se].value--
if(sem[se].value==0) return(1) //判断是否有资源
printf("阻塞当前进程%d\n",p) //打印阻塞进程
pcb[p].pstatus='w' //把阻塞进程置"w"状态
ep=0
pcb[p].waiter1=0
w=sem[se].waiter2
//下一状态指示字赋给w
if(w==0) sem[se].waiter2=p //把等待进程标识符送入信号单元
else{
while(pcb[w].waiter1!=0) //找等待队列是否为空
w=pcb[w].waiter1 //送入等待指示字单元
pcb[w].waiter1=p //否则插入等待队列
}
stack[1][p]=i
stack[2][p]=ad// 保护现场
return(0)
}
int v(int se,int p,char ad){
int w
sem[se].value++
if(sem[se].value>0) return(1)
w=sem[se].waiter2
sem[se].waiter2=pcb[w].waiter1
pcb[w].pstatus='t'
printf("唤醒进程%d\n",w)
stack[1][p]=i
stack[2][p]=ad
return(0)
}
1. 哲学家进餐问题:(1) 在什么情况下5 个哲学家全部吃不上饭?
考虑两种实现的方式,如下:
A.
算法描述:
void philosopher(int i) /*i:哲学家编号,从0 到4*/
{
while (TRUE) {
think( )/*哲学家正在思考*/
take_fork(i)/*取左侧的筷子*/
take_fork((i+1) % N)/*取左侧筷子;%为取模运算*/
eat( )/*吃饭*/
put_fork(i)/*把左侧筷子放回桌子*/
put_fork((i+1) % N)/*把右侧筷子放回桌子*/
}
}
分析:假如所有的哲学家都同时拿起左侧筷子,看到右侧筷子不可用,又都放下左侧筷子,
等一会儿,又同时拿起左侧筷子,如此这般,永远重复。对于这种情况,即所有的程序都在
无限期地运行,但是都无法取得任何进展,即出现饥饿,所有哲学家都吃不上饭。
B.
算法描述:
规定在拿到左侧的筷子后,先检查右面的筷子是否可用。如果不可用,则先放下左侧筷子,
等一段时间再重复整个过程。
分析:当出现以下情形,在某一个瞬间,所有的哲学家都同时启动这个算法,拿起左侧的筷
子,而看到右侧筷子不可用,又都放下左侧筷子,等一会儿,又同时拿起左侧筷子……如此
这样永远重复下去。对于这种情况,所有的程序都在运行,但却无法取得进展,即出现饥饿,
所有的哲学家都吃不上饭。
(2) 描述一种没有人饿死(永远拿不到筷子)算法。
考虑了四种实现的方式(A、B、C、D):
A.原理:至多只允许四个哲学家同时进餐,以保证至少有一个哲学家能够进餐,最终总会释
放出他所使用过的两支筷子,从而可使更多的哲学家进餐。以下将room 作为信号量,只允
许4 个哲学家同时进入餐厅就餐,这样就能保证至少有一个哲学家可以就餐,而申请进入
餐厅的哲学家进入room 的等待队列,根据FIFO 的原则,总会进入到餐厅就餐,因此不会
出现饿死和死锁的现象。
伪码:
semaphore chopstick[5]={1,1,1,1,1}
semaphore room=4
void philosopher(int i)
{
while(true)
{
think()
wait(room)//请求进入房间进餐
wait(chopstick[i])//请求左手边的筷子
wait(chopstick[(i+1)%5])//请求右手边的筷子
eat()
signal(chopstick[(i+1)%5])//释放右手边的筷子
signal(chopstick[i])//释放左手边的筷子
signal(room)//退出房间释放信号量room
}
}
B.原理:仅当哲学家的左右两支筷子都可用时,才允许他拿起筷子进餐。
方法1:利用AND 型信号量机制实现:根据课程讲述,在一个原语中,将一段代码同时需
要的多个临界资源,要么全部分配给它,要么一个都不分配,因此不会出现死锁的情形。当
某些资源不够时阻塞调用进程由于等待队列的存在,使得对资源的请求满足FIFO 的要求,
因此不会出现饥饿的情形。
伪码:
semaphore chopstick[5]={1,1,1,1,1}
void philosopher(int I)
{
while(true)
{
think()
Swait(chopstick[(I+1)]%5,chopstick[I])
eat()
Ssignal(chopstick[(I+1)]%5,chopstick[I])
}
}
方法2:利用信号量的保护机制实现。通过信号量mutex对eat()之前的取左侧和右侧筷
子的操作进行保护,使之成为一个原子操作,这样可以防止死锁的出现。
伪码:
semaphore mutex = 1
semaphore chopstick[5]={1,1,1,1,1}
void philosopher(int I)
{
while(true)
{
think()
wait(mutex)
wait(chopstick[(I+1)]%5)
wait(chopstick[I])
signal(mutex)
eat()
signal(chopstick[(I+1)]%5)
signal(chopstick[I])
}
}
C. 原理:规定奇数号的哲学家先拿起他左边的筷子,然后再去拿他右边的筷子而偶数号
的哲学家则相反.按此规定,将是1,2号哲学家竞争1号筷子,3,4号哲学家竞争3号筷子.即
五个哲学家都竞争奇数号筷子,获得后,再去竞争偶数号筷子,最后总会有一个哲学家能获
得两支筷子而进餐。而申请不到的哲学家进入阻塞等待队列,根FIFO原则,则先申请的哲
学家会较先可以吃饭,因此不会出现饿死的哲学家。
伪码:
semaphore chopstick[5]={1,1,1,1,1}
void philosopher(int i)
{
while(true)
{
think()
if(i%2 == 0) //偶数哲学家,先右后左。
{
wait (chopstick[ i + 1 ] mod 5)
wait (chopstick[ i])
eat()
signal (chopstick[ i + 1 ] mod 5)
signal (chopstick[ i])
}
Else //奇数哲学家,先左后右。
{
wait (chopstick[ i])
wait (chopstick[ i + 1 ] mod 5)
eat()
signal (chopstick[ i])
signal (chopstick[ i + 1 ] mod 5)
}
}
D.利用管程机制实现(最终该实现是失败的,见以下分析):
原理:不是对每只筷子设置信号量,而是对每个哲学家设置信号量。test()函数有以下作
用:
a. 如果当前处理的哲学家处于饥饿状态且两侧哲学家不在吃饭状态,则当前哲学家通过
test()函数试图进入吃饭状态。
b. 如果通过test()进入吃饭状态不成功,那么当前哲学家就在该信号量阻塞等待,直到
其他的哲学家进程通过test()将该哲学家的状态设置为EATING。
c. 当一个哲学家进程调用put_forks()放下筷子的时候,会通过test()测试它的邻居,
如果邻居处于饥饿状态,且该邻居的邻居不在吃饭状态,则该邻居进入吃饭状态。
由上所述,该算法不会出现死锁,因为一个哲学家只有在两个邻座都不在进餐时,才允
许转换到进餐状态。
该算法会出现某个哲学家适终无法吃饭的情况,即当该哲学家的左右两个哲学家交替
处在吃饭的状态的时候,则该哲学家始终无法进入吃饭的状态,因此不满足题目的要求。
但是该算法能够实现对于任意多位哲学家的情况都能获得最大的并行度,因此具有重要
的意义。
伪码:
#define N 5 /* 哲学家人数*/
#define LEFT (i-1+N)%N /* i的左邻号码 */
#define RIGHT (i+1)%N /* i的右邻号码 */
typedef enum { THINKING, HUNGRY, EATING } phil_state/*哲学家状态*/
monitor dp /*管程*/
{
phil_state state[N]
semaphore mutex =1
semaphore s[N]/*每个哲学家一个信号量,初始值为0*/
void test(int i)
{
if ( state[i] == HUNGRY &&state[LEFT(i)] != EATING &&
state[RIGHT(i)] != EATING )
{
state[i] = EATING
V(s[i])
}
}
void get_forks(int i)
{
P(mutex)
state[i] = HUNGRY
test(i)/*试图得到两支筷子*/
V(mutex)
P(s[i])/*得不到筷子则阻塞*/
}
void put_forks(int i)
{
P(mutex)
state[i]= THINKING
test(LEFT(i))/*看左邻是否进餐*/
test(RIGHT(i))/*看右邻是否进餐*/
V(mutex)
}
}
哲学家进程如下:
void philosopher(int process)
{
while(true)
{
think()
get_forks(process)
eat()
put_forks(process)
}
}
欢迎分享,转载请注明来源:夏雨云
评论列表(0条)