用带头结点的单链表实现生产者消费者模型

一、多线程的售票引发的问题

多线程间Linux下线程和线程共享全局变量、代码段、数据段、文件描述符表,这么多的临界资源在使用时也可能会带来一些麻烦

例如:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>

int ticket = 100;
void *route(void *arg)
{
 char *id = (char*)arg;
 while ( 1 ) {
 if ( ticket > 0 ) {
 usleep(1000);
 printf("%s sells ticket:%d\n", id, ticket);
 ticket--;
 } else {
 break;
        }
    }
}

int main()
{
 pthread_t t1, t2, t3;
 pthread_create(&t1, NULL, route, "thread 1");
 pthread_create(&t2, NULL, route, "thread 2");
 pthread_create(&t3, NULL, route, "thread 3");

 pthread_join(t1,NULL);
 pthread_join(t2,NULL);
 pthread_join(t3,NULL);
}

不同的执行流对同一个全局变量进行操作,这个操作不是原子的。从内存读到CPU中,CPU中进行操作,操作后写回到内存中,步骤2完成后进程切换出去,保存操作2之后的数据进行等待,后续线程依然从起始的数开始操作,等所有的操作完成后都一起返回,第一个操作返回的数据是第一次操作后的。

第一个线程在CPU中将100张票减一后被切换出CPU,此时内存中的票数还是100张,线程2从内存中读取出票数进行减减操作(还是从100开始减减)等所有的进程都操作完成后线程一写回内存时票数是当时操作完的99张。造成一张票被卖出多次的情况。

这时就需要使用线程的同步与互斥机制保护临界资源,互斥说明一个线程在操作临界资源时其他线程不能访问临界资源,同步说明多个线程在访问临界资源时是按照一定顺序访问的。

二、线程互斥锁

线程中 互斥:互斥锁

定义互斥锁:pthread_mutex_t lock;

初始化:pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr);

mutex:要初始化的互斥量
 attr:NULL

销毁:pthread_mutex_destroy(pthread_mutex_t *mutex);

注意不要销毁一个已经加锁的互斥量,已经销毁的互斥量要确保后面不会再次被加锁

加锁:pthread_lock(pthread_mutex_t *mutex);

解锁:pthread_unclock(pthread_mutex_t *mutex);

加锁和解锁成功返回0,失败返回错误码。

其他线程已经锁定互斥量,或者存在其他线程同时申请互斥量,但没有竞争到互
斥量,那么pthread_ lock调⽤会陷⼊阻塞等待互斥量解锁

三、生产者消费者模型

三个关系:生产者与生产者之间互斥关系,生产者与消费者之间互斥且同步关系(放的同时取,是放还是没放,取还是没取二义性;必须有人买才能添加,必须有人添加才能消费)消费者与消费者之间互斥关系,使用互斥锁。

两个角色:生产者消费者

一个场所:只要能存取数据就可以

实现一个生产场所为带头单链表的生产者消费者模型:

**因为优先级或避免竞争能力强的线程不断的获取锁释放锁,另一个进程得不到锁,饥饿问题数据

条件变量可以很好的解决

条件变量:线程间同步,当⼀个线程互斥地访问某个变量时,它可能发现在其它线程改变状态之前,它什么也做不了只能等待。直到其他线程将状态改变例如,消费者互斥的访问链表消费场所为空时消费者就一直等待,等待生产者生产一个结点加入链表,pthread_cond_wait()必须与互斥锁配合使用

如果不符合条件就不获取锁int pthread_cond_wait()等的时候默认释放锁,等的时候什么都不干,如果不释放锁没人释放了别的线程不能获取到锁,造成了死锁问题(已经进入获取到锁了),被signal或其他方式唤醒时重新获得锁并从等待处继续执行

1 //单生产者单消费者                                                                                                   
  2 //带头的单向链表作为交易场所                                                                                         
  3 #include <stdio.h>                                                                                                   
  4 #include <sys/types.h>                                                                                               
  5 #include <unistd.h>                                                                                                  
  6 #include <pthread.h>                                                                                                 
  7 #include <sys/syscall.h>                                                                                             
  8 #include <stdlib.h>                                                                                                  
  9 #include <pthread.h>                                                                                                 
 10 typedef struct _Node                                                                                                 
 11 {                                                                                                                    
 12   int data;                                                                                                          
 13   struct _Node *next;                                                                                                
 14 }node_t,*node_p,**node_pp;                                                                                           
 15 pthread_mutex_t lock;                                                                                                
 16 pthread_cond_t cond;                                                                                                 
 17 node_p Create_Node(int data)                                                                                         
 18 {                                                                                                                    
 19   node_p new_node = (node_p)malloc(sizeof(node_t));  
 20   if(new_node == NULL)                                                                                               
 21   {                                                                                                                  
 22     perror("malloc\n");                                                                                              
 23     exit(1);                                                                                                         
 24   }                                                                                                                  
 25   new_node->data = data;                                                                                             
 26   new_node->next = NULL;                                                                                             
 27   return new_node;                                                                                                   
 28 }                                                                                                                    
 29                                                                                                                      
 30 void DestroyNode(node_p to_delete)                                                                                   
 31 {                                                                                                                    
 32   if(to_delete != NULL)                                                                                              
 33   {                                                                                                                  
 34     free(to_delete);                                                                                                 
 35     to_delete = NULL;                                                                                                
 36   }                                                                                                                  
 37 }                                                                                                                    
 38 void Init_List(node_pp head) 
 {                                                                                                                    
 40  // head = Create_Node(0);                                                                                           
 41     *head = Create_Node(0);                                                                                          
 42 }                                                                                                                    
 43                                                                                                                      
 44 void Link_Push(node_p head,int num)                                                                                  
 45 {                                                                                                                    
 46   node_p new_node = Create_Node(num);                                                                                
 47   new_node->next = head->next;                                                                                       
 48   head->next = new_node;                                                                                             
 49 }                                                                                                                    
 50                                                                                                                      
 51 void List_Pop(node_p head,int *num)//输出型参数                                                                      
 52 {                                                                                                                    
 53   if(head->next != NULL)                                                                                             
 54   {                                                                                                                  
 55     node_p to_delete = head->next;                                                                                   
 56     *num = to_delete->data;                                                                                          
 57     head->next = to_delete->next;   
    DestroyNode(to_delete);                                                                                          
 59   }                                                                                                                  
 60 }                                                                                                                    
 61                                                                                                                      
 62 void PrintList(node_p head)                                                                                          
 63 {                                                                                                                    
 64   node_p cur = head->next;                                                                                           
 65   if(cur != NULL)                                                                                                    
 66   {                                                                                                                  
 67     printf("%d | %p\n",cur->data, cur);                                                                              
 68     cur = cur->next;                                                                                                 
 69   }                                                                                                                  
 70 }                                                                                                                    
 71                                                                                                                      
 72 void DestroyList(node_p head)                                                                                        
 73 {                                                                                                                    
 74   int x;                                                                                                             
 75   node_p cur = head->next;                                                                                           
 76   if(cur != NULL)       
 77   {                                                                                                                  
 78     List_Pop(head,&x);                                                                                               
 79     cur = cur->next;                                                                                                 
 80   }                                                                                                                  
 81   free(head);                                                                                                        
 82 }                                                                                                                    
 83                                                                                                                      
 84 void *consumer(void *arg)                                                                                            
 85 {                                                                                                                    
 86   node_p head = (node_p )arg;                                                                                        
 87   while(1)                                                                                                           
 88   {                                                                                                                  
 89     int data = 0;                                                                                                    
 90     pthread_mutex_lock(&lock);                                                                                       
 91     while(head->next == NULL)                                                                                        
 92     {                                                                                                                
 93       printf("no data for consume\n");//什么都没干就只有申请锁释放锁    
 94       pthread_cond_wait(&cond,&lock);//没有数据不可以消费就等待,释放锁,条件变量实现了同步                          
 95       //可能被异常唤醒,消费场所里还是没有数据while循环进行判断                                                      
 96     }                                                                                                                
 97     List_Pop(head,&data);                                                                                            
 98     printf("consumer done! data = %d\n",data);                                                                       
 99     pthread_mutex_unlock(&lock);//退出前解锁                                                                         
100     sleep(1);                                                                                                        
101   }                                                                                                                  
102 }                                                                                                                    
103                                                                                                                      
104 void *producter(void *arg)                                                                                           
105 {                                                                                                                    
106   node_p head = (node_p )arg;                                                                                        
107   while(1)                                                                                                           
108   {                                                                                                                  
109     int data = 0;                                                                                                    
110     data = rand()%100+1;                                                                                             
111     pthread_mutex_lock(&lock); 
112     Link_Push(head,data);//放入消费场所                                                                              
113     pthread_mutex_unlock(&lock);                                                                                     
114     //pthread_cond_signal(&cond);//放入后唤醒等待条件变量                                                            
115     pthread_cond_broadcast(&cond);//通知所有的线程                                                                   
116     printf("product down data = %d\n",data);                                                                         
117     sleep(5);                                                                                                        
118   }                                                                                                                  
119 }                                                                                                                    
120 int main()                                                                                                           
121 {                                                                                                                    
122   pthread_mutex_init(&lock,NULL);                                                                                    
123   pthread_cond_init(&cond,NULL);                                                                                     
124   node_p  head;                                                                                                      
125   Init_List(&head);                                                                                                  
126   srand((unsigned long)time(NULL));                                                                                  
127   pthread_t p,c;                                                                                                     
128   pthread_create(&c,NULL,consumer,(void *)head);                                                                     
129   pthread_create(&p,NULL,producter,(void *)head);  
130                                                                                                                      
131   pthread_join(c,NULL);                                                                                              
132   pthread_join(p,NULL);                                                                                              
133   pthread_mutex_destroy(&lock);                                                                                      
134   pthread_cond_destroy(&cond); 
135 }       

猜你喜欢

转载自blog.csdn.net/jane_yao/article/details/82120405