线程同步机制

来源:互联网 发布:雨过天晴还原软件 编辑:程序博客网 时间:2024/05/21 07:00

本周主要学习线程同步机制(互斥量、读写锁和条件变量)和简单程序的实现,对线程同步有了进一步认识
内容如下:
1、线程的基本概念,相关函数
2、互斥量
线程同步的三种基本同步机制 - xynice - altercrazy

说明

·         处于标圆形框之上的线段表示相关的线程没有拥有互斥量;

·         处于圆形框中心线之上的线段表示相关的线程等待互斥量;

·         处于圆形框中心线之下的线段表示相关的线程拥有互斥量;

过程描述

·         最初,互斥量没有被加锁;

·         当线程1试图加锁该互斥量时,因为没有竞争,线程1立即加锁成功,对应线段也移到中心线之下;

·         然后线程2试图加锁互斥量,由于互斥量已经被加锁,所以线程2被阻塞,对应线段在中心线之上;

·         接着,线程1解锁互斥量,于是线程2解除阻塞,并对互斥量加锁成功;

·         然后,线程3试图加锁互斥量,同样被阻塞;

·         此时,线程1调用函数pthread_mutext_trylock试图加锁互斥量,而立即返回EBUSY

·         然后,线程2解锁互斥量,解除线程3的阻塞,线程3加锁成功;

·         最后,线程3完成工作,解锁互斥量

3、读写锁

     读写锁实际是一种特殊的自旋锁,它把对共享资源的访问者划分成读者和写者,读者只对共享资源进行读访问,写者则需要对共享资源进行写操作。这种锁相对于自旋锁而言,能提高并发性,因为在多处理器系统中,它允许同时有多个读者来访问共享资源,最大可能的读者数为实际的逻辑CPU数。写者是排他性的,一个读写锁同时只能有一个写者或多个读者(与CPU数相关),但不能同时既有读者又有写者。

代码实现功能:使用读写锁实现四个线程读写一段程序,共建了四个线程,其中两个线程用来读数据,另外两个线程用来写数据,在任意时刻,如果有一个线程在写数据,将阻塞其他线程的任何操作。

#include <errno.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <bits/pthreadtypes.h>

static pthread_rwlock_t rwlock;

#define WORK_SIZE 1024
char work_area[WORK_SIZE];
int time_to_exit;

void *thread_function_read_o(void *arg); //read
void *thread_function_read_t(void *arg);
void *thread_function_write_o(void *arg); //write
void *thread_function_write_t(void *arg);


int main(int argc,char *argv[]){
int res;
pthread_t a_thread, b_thread, c_thread, d_thread;
void *thread_result;

res=pthread_rwlock_init(&rwlock,NULL);
if (res != 0){
perror("rwlock initialization failed");
exit(EXIT_FAILURE);
}

res = pthread_create(&a_thread, NULL, thread_function_read_o, NULL);
if (res != 0){
perror("Thread creation failed");
exit(EXIT_FAILURE);
}

res = pthread_create(&b_thread, NULL, thread_function_read_t, NULL);//create new thread
if (res != 0){
perror("Thread creation failed");
exit(EXIT_FAILURE);
}

res = pthread_create(&c_thread, NULL, thread_function_write_o, NULL);//create new thread
if (res != 0){
perror("Thread creation failed");
exit(EXIT_FAILURE);
}

res = pthread_create(&d_thread, NULL, thread_function_write_t, NULL);//create new thread
if (res != 0){
perror("Thread creation failed");
exit(EXIT_FAILURE);
}

res = pthread_join(a_thread, &thread_result);//等待a_thread线程结束
if (res != 0){
perror("Thread join failed");
exit(EXIT_FAILURE);
}

res = pthread_join(b_thread, &thread_result);
if (res != 0){
perror("Thread join failed");
exit(EXIT_FAILURE);
}

res = pthread_join(c_thread, &thread_result);
if (res != 0){
perror("Thread join failed");
exit(EXIT_FAILURE);
}

res = pthread_join(d_thread, &thread_result);
if (res != 0){
perror("Thread join failed");
exit(EXIT_FAILURE);
}

pthread_rwlock_destroy(&rwlock);//销毁读写锁
exit(EXIT_SUCCESS);
}

void *thread_function_read_o(void *arg)
{
printf("thread read one try to get lock\n");

pthread_rwlock_rdlock(&rwlock);//获取读取锁
while(strncmp("end", work_area, 3) != 0)
{
printf("this is thread read one.");
printf("the characters is %s",work_area);

pthread_rwlock_unlock(&rwlock);
sleep(2);
pthread_rwlock_rdlock(&rwlock);
while (work_area[0] == '\0' )
{
pthread_rwlock_unlock(&rwlock);
sleep(2);
pthread_rwlock_rdlock(&rwlock);
}

}
pthread_rwlock_unlock(&rwlock);
time_to_exit=1;
pthread_exit(0);
}

void *thread_function_read_t(void *arg)
{
printf("thread read one try to get lock\n");
pthread_rwlock_rdlock(&rwlock);
while(strncmp("end", work_area, 3) != 0)
{
printf("this is thread read two.");
printf("the characters is %s",work_area);

pthread_rwlock_unlock(&rwlock);
sleep(3);
pthread_rwlock_rdlock(&rwlock);
while (work_area[0] == '\0' )
{
pthread_rwlock_unlock(&rwlock);
sleep(3);
pthread_rwlock_rdlock(&rwlock);
}
}
pthread_rwlock_unlock(&rwlock);
time_to_exit=1;
pthread_exit(0);
}

void *thread_function_write_o(void *arg)
{
printf("this is write thread one try to get lock\n\n");
while(!time_to_exit) //cause every Read have changed the Time_to_Exit=1, so if Time_to_Exit!=1,this is Write
{
pthread_rwlock_wrlock(&rwlock);
printf("this is write thread one.\nInput some text. Enter 'end' to finish...\n");
fgets(work_area, WORK_SIZE, stdin);
pthread_rwlock_unlock(&rwlock);
sleep(7);
}
pthread_rwlock_unlock(&rwlock);
pthread_exit(0);
}

void *thread_function_write_t(void *arg)
{
sleep(4);
while(!time_to_exit)
{
pthread_rwlock_wrlock(&rwlock);//获取写入锁
printf("this is write thread two.\nInput some text. Enter 'end' to finish...\n");
fgets(work_area, WORK_SIZE, stdin);//写入
pthread_rwlock_unlock(&rwlock);//解锁
sleep(10);
}
pthread_rwlock_unlock(&rwlock);//解锁
pthread_exit(0);
}


 4、条件变量(难点

类型声明:pthread_cond_t cond; 

对条件变量的初始化:程序在使用pthread_cond_t变量之前必须对其进行初始化。对于静态的pthread_cond_t变量来说,是要将PTHREAD_COND_INITIALIZER赋给变量;对于动态分配的或没有默认属性的变量来说,就要调用pthread_cond_init函数来执行初始化。

对条件变量的操作:

 int pthread_cond_wait(pthread_cond_* cond,pthread_mutex_t* mutex);//使线程阻塞于某个条件。 

     int pthread_cond_signal(pthread_cond_t* cond);//唤醒某个阻塞在cond上的线程。 

    对条件变量的销毁: int pthread_cond_destroy(pthread_cond_t* cond); 

代码实现功能:一个int型全局变量g_Flag初始值为0,在主线程中启动线程1,打印“this is thread1”,将g_Flag设置为1,在主线程中启动线程2,打印“this is thread2”,将g_Flag设置为2,线程1在线程2退出后退出,主线程在检测到g_Flag从1变成2,或者从2变成1退出。

#include<stdio.h>

#include<stdlib.h>
#include<pthread.h>
#include<errno.h>
#include<unistd.h>

typedef void* (*fun)(void*);
int g_Flag=0;
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
void* thread1(void*);
void* thread2(void*);

int main(int argc, char** argv)
{
printf("enter main\n");

pthread_t tid1, tid2;
int rc1=0, rc2=0;

rc2 = pthread_create(&tid2, NULL, thread2, NULL);
if(rc2 != 0)
printf("%s: %d\n",__func__, strerror(rc2));

rc1 = pthread_create(&tid1, NULL, thread1, &tid2);
if(rc1 != 0)
printf("%s: %d\n",__func__, strerror(rc1));

pthread_cond_wait(&cond, &mutex);
printf("leave main\n");

exit(0);
}

void* thread1(void* arg)
{
printf("enter thread1\n");
printf("this is thread1, g_Flag: %d, thread id is %u\n",g_Flag, (unsigned int)pthread_self());
pthread_mutex_lock(&mutex);

if(g_Flag == 2)
pthread_cond_signal(&cond);
g_Flag = 1;

printf("this is thread1, g_Flag: %d, thread id is %u\n",g_Flag, (unsigned int)pthread_self());

pthread_mutex_unlock(&mutex);
pthread_join(*(pthread_t*)arg, NULL);
printf("leave thread1\n");
pthread_exit(0);
}

void* thread2(void* arg)
{
printf("enter thread2\n");
printf("this is thread2, g_Flag: %d, thread id is %u\n",g_Flag, (unsigned int)pthread_self());
pthread_mutex_lock(&mutex);

if(g_Flag == 1)
pthread_cond_signal(&cond);
g_Flag = 2;

printf("this is thread2, g_Flag: %d, thread id is %u\n",g_Flag, (unsigned int)pthread_self());
pthread_mutex_unlock(&mutex);
printf("leave thread2\n");
pthread_exit(0);
}

原创粉丝点击