概念
线程是可以共享资源变量的,当多个线程同时写一个资源变量时就会出现线程同步问题造成读写不一致。通常采用锁机制来实现线程同步。
1 互斥量:锁机制,确保同一时刻只有一个线程访问共享资源。
常用API包括:
int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr);
int pthread_mutex_destroy(pthread_mutex_t *mutex);
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);
int pthread_mutex_trylock(pthread_mutex_t *mutex);
不采用互斥量的多线程问题:
void *func2(void *p)
{
char *file_name = "/tmp/out";
FILE *fp;
char linebuf[1024];
fp = fopen(file_name, "r+");
if(fp == NULL)
{
perror("fopen()");
exit(-1);
}
fgets(linebuf, 1024, fp);
fseek(fp, 0, SEEK_SET);
fprintf(fp, "%d\n", atoi(linebuf)+1);
fclose(fp);
pthread_exit(NULL);
}
void test2()
{
int err, num = 20;
pthread_t tid[num];
for(int i=0; i<num; i++)
{
err = pthread_create(tid+i, NULL, func2, NULL);
if(err)
{
fprintf(stdout,"pthread_create %s\n", strerror(err));
exit(1);
}
}
}
采用互斥量的多线程:
void *func3(void *p)
{
char *file_name = "/tmp/out";
FILE *fp;
char linebuf[1024];
fp = fopen(file_name, "r+");
if(fp == NULL)
{
perror("fopen()");
exit(-1);
}
pthread_mutex_lock(&mut);
fgets(linebuf, 1024, fp);
fseek(fp, 0, SEEK_SET);
fprintf(fp, "%d\n", atoi(linebuf)+1);
fclose(fp);
pthread_mutex_unlock(&mut);
pthread_exit(NULL);
}
void test3()
{
int err, num = 20;
pthread_t tid[num];
for(int i=0; i<num; i++)
{
err = pthread_create(tid+i, NULL, func3, NULL);
if(err)
{
fprintf(stdout,"pthread_create %s\n", strerror(err));
exit(1);
}
}
for(int i=0; i<num; i++)
pthread_join(tid[i], NULL);
pthread_mutex_destroy(&mut);
exit(0);
}
4个线程依次输出abcd,如何实现?
#include<stdio.h>
#include<stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <string.h>
static pthread_mutex_t mut[4];
int next(int n)
{
if(n+1 == 4)
return 0;
return n+1;
}
void *func(void *p)
{
int i = (int) p;
while(1){
pthread_mutex_lock(mut+i); //锁自己接下一个人的锁
switch (i)
{
case 0:
putchar('a');
break;
case 1:
putchar('b');
break;
case 2:
putchar('c');
break;
case 3:
putchar('d');
break;
default:
break;
}
pthread_mutex_unlock(mut+next(i));
}
putchar('\n');
pthread_exit(NULL);
}
int main(int argc, char **argv)
{
int i,err;
int num = 4;
pthread_t tid[num];
for(i=0;i<num;i++)
{
pthread_mutex_init(mut+i, NULL);
pthread_mutex_lock(mut+i);
err = pthread_create(tid+i, NULL, func, (void *)i); //i一个地址被201个指针指向
if(err)
{
fprintf(stdout,"pthread_create %s\n", strerror(err));
exit(1);
}
}
alarm(2); //定时杀死进程
pthread_mutex_unlock(mut);
for(i=0;i<num;i++)
{
pthread_join(tid[i], NULL);
}
pthread_mutex_destroy(&mut);
exit(0);
}
2 条件变量:是一种通知法机制,避免资源不够时的忙等。
#include<stdio.h>
#include<stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <string.h>
#define LEFT 30000000
#define RIGHT 30011911
#define THRUNM 3
//全局变量负责记录资源
static int num=0;
//互斥量
static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t condt = PTHREAD_COND_INITIALIZER;
void *func(void *p)
{
int i,mark,j;
int number = (int) p;
while(1)
{
pthread_mutex_lock(&mut);
while(num == 0)
{
pthread_cond_wait(&condt, &mut);
}
if(num == -1)
{
pthread_mutex_unlock(&mut);
break;
}
i = num;
num = 0;
pthread_cond_broadcast(&condt);
pthread_mutex_unlock(&mut);
mark =1;
for(j=2; j<i/2;j++)
{
if(i%j == 0)
{
mark =0;
break;
}
}
if(mark) {
printf("%d号线程计算出来:%d is primer\n", number,i);
}
}
pthread_exit(NULL);
}
int main(int argc, char **argv)
{
int i,err;
pthread_t tid[THRUNM];
for(i=0;i<THRUNM;i++)
{
err = pthread_create(tid+i, NULL, func, (void *)i); //i一个地址被THRUNM个指针指向
if(err)
{
fprintf(stdout,"pthread_create %s\n", strerror(err));
exit(1);
}
}
//main线程负责下发任务
for(i=LEFT;i<=RIGHT;i++)
{
pthread_mutex_lock(&mut);
//任务还在未被抢走
while(num != 0)
{
pthread_cond_wait(&condt, &mut);
}
num = i;
pthread_cond_signal(&condt);
pthread_mutex_unlock(&mut);
}
pthread_mutex_lock(&mut);
while(num != 0) {
pthread_mutex_unlock(&mut);
sched_yield();
pthread_mutex_lock(&mut);
}
//退出线程
num = -1;
pthread_cond_broadcast(&condt);
pthread_mutex_unlock(&mut);
for(i=0;i<THRUNM;i++)
{
pthread_join(tid[i], NULL);
}
pthread_mutex_destroy(&mut);
pthread_cond_destroy(&condt);
exit(0);
}