在Linux环境下进程的互斥是通过创建一个互斥锁来实现的当线程某一资源进行访问时通过给这一资源加锁来防止其他线程对其访问,每一个线程要访问这一资源是必须先申请锁如果得到了锁就可以对资源进行访问,如果没有就会挂起等待。
比如定义一个全局变量用两个线程分别对其进行加加5000次看其结果
#include <pthread.h>
int pthread_mutex_destroy(pthread_mutex_t *mutex);
int pthread_mutex_init(pthread_mutex_t *restrict mutex,
const pthread_mutexattr_t *restrict attr);
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
#include <pthread.h>
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_trylock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);
#include<stdio.h>
#include<unistd.h>
#include<pthread.h>
#include<stdlib.h>
int g_val = 0;
void* thread1(void* val)
{
int i=0;
for(i = 0; i<5000; i++)
{
int a = g_val;
a++;
printf(" ");
printf("tid1 = %lu,g_val = %d",pthread_self(),a);
printf("\n");
g_val = a;
}
}
void* thread2(void* val)
{
int i = 0;
for(i = 0; i<5000; i++)
{
int a = g_val;
a++;
printf(" ");
printf("tid2 = %lu,g_val = %d",pthread_self(),a);
printf("\n");
g_val = a;
}
}
int main()
{
pthread_t tid1;
pthread_t tid2;
int ret1 = pthread_create(&tid1,NULL,thread1,NULL);
if (ret1 != 0)
{
perror("pthread_create:");
}
int ret2 = pthread_create(&tid2,NULL,thread2,NULL);
if (ret2 != 0)
{
perror("pthread_create:");
}
void *p1 = NULL;
void *p2 = NULL;
pthread_join(tid1,&p1);
pthread_join(tid2,&p2);
printf("pid = %d,tid1 = %lu,p1 = %d\n",getpid(),tid1,p1);
printf("pid = %d,tid2 = %lu,p2 = %d\n",getpid(),tid2,p2);
return 0;
}
对上面的代码稍作改动加入互斥锁
#include<stdio.h>
#include<unistd.h>
#include<pthread.h>
#include<stdlib.h>
int g_val = 0;
pthread_mutex_t mutex_lock = PTHREAD_MUTEX_INITIALIZER;
void* thread1(void* val)
{
int i=0;
for(i = 0; i<5000; i++)
{
pthread_mutex_lock(&mutex_lock);
int a = g_val;
a++;
printf(" ");
printf("tid1 = %lu,g_val = %d",pthread_self(),a);
printf("\n");
g_val = a;
pthread_mutex_unlock(&mutex_lock);
}
}
void* thread2(void* val)
{
int i = 0;
for(i = 0; i<5000; i++)
{
pthread_mutex_lock(&mutex_lock);
int a = g_val;
a++;
printf(" ");
printf("tid2 = %lu,g_val = %d",pthread_self(),a);
printf("\n");
g_val = a;
pthread_mutex_unlock(&mutex_lock);
}
}
int main()
{
pthread_t tid1;
pthread_t tid2;
int ret1 = pthread_create(&tid1,NULL,thread1,NULL);
if (ret1 != 0)
{
perror("pthread_create:");
}
int ret2 = pthread_create(&tid2,NULL,thread2,NULL);
if (ret2 != 0)
{
perror("pthread_create:");
}
void *p1 = NULL;
void *p2 = NULL;
pthread_join(tid1,&p1);
pthread_join(tid2,&p2);
printf("pid = %d,tid1 = %lu,p1 = %d\n",getpid(),tid1,p1);
printf("pid = %d,tid2 = %lu,p2 = %d\n",getpid(),tid2,p2);
return 0;
}
在上面的例子中只体现了线程的互斥并没有体现出线程的同步在某一段时间内都是一个线程的输出
Linux用条件变量来实现进程同步
下面用条件变量来实现线程同步解决生产者消费者问题用一个单链表来作为数据缓冲区
#include <pthread.h>
int pthread_cond_timedwait(pthread_cond_t *restrict cond,
pthread_mutex_t *restrict mutex,
const struct timespec *restrict abstime);
int pthread_cond_wait(pthread_cond_t *restrict cond,
pthread_mutex_t *restrict mutex);
#include <pthread.h>
int pthread_cond_destroy(pthread_cond_t *cond);
int pthread_cond_init(pthread_cond_t *restrict cond,
const pthread_condattr_t *restrict attr);
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<pthread.h>
#include<assert.h>
typedef struct node
{
int _data;
struct node* _next;
}node,*node_p,**node_pp;
node_p alloc_node(int _d)
{
node_p tmp = (node_p)malloc(sizeof(node));
if(!tmp)
{
perror("malloc :");
exit(1);
}
tmp->_data = _d;
tmp->_next = NULL;
return tmp;
}
void push_node(node_p _h,int _d)
{
assert(_h);
node_p tmp = alloc_node(_d);
tmp->_next = _h->_next;
_h->_next = tmp;
}
void destroy(node_p _h)
{
assert(_h);
while(_h)
{
pop_node(_h);
}
free(_h);
}
int empty(node_p _h)
{
return (_h->_next == NULL)?1:0;
}
int pop_node(node_p _h)
{
assert(_h);
int data;
if(!empty(_h))
{
node_p tmp = _h->_next;
_h->_next = tmp->_next;
data = tmp->_data;
free(tmp);
}
return data;
}
void init_node(node_pp _h)
{
assert(_h);
*_h = alloc_node(0);
}
void print_node(const node_p _h)
{
assert(_h);
node_p tmp = _h->_next;
while(tmp)
{
printf("%d ",tmp->_data);
tmp = tmp->_next;
}
printf("\n");
}
pthread_mutex_t lock =PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
void* product(void* arg)
{
node_p h = (node_p)arg;
while(1)
{
pthread_mutex_lock(&lock);
int data = rand()%1000;
push_node(h,data);
printf("product %d \n",data);
pthread_mutex_unlock(&lock);
sleep(1);
pthread_cond_signal(&cond);
}
}
void* consumer(void* arg)
{
node_p h = (node_p)arg;
while(1)
{
pthread_mutex_lock(&lock);
int data;
while(empty(h));
{
printf("no prodouct...consumer wait\n");
pthread_cond_wait(&cond,&lock);
printf("consumer is wake\n");
}
data = pop_node(h);
printf("consumer %d \n",data);
pthread_mutex_unlock(&lock);
}
}
int main()
{
node_p head;
init_node(&head);
pthread_t tid1;
pthread_t tid2;
pthread_create(&tid1,NULL,product,head);
pthread_create(&tid2,NULL,consumer,head);
pthread_join(tid1,NULL);
pthread_join(tid2,NULL);
pthread_mutex_destroy(&lock);
pthread_cond_destroy(&cond);
destroy(head);
return 0;
}