看如下程序:该程序是非常典型的,由于共享、竞争而没有加任何同步机制,导致产生于时间有关的错误,造成数据混乱:
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
void *tfn(void arg)
{
srand(time(NULL));
while (1) {
printf("hello ");
sleep(rand() % 3); //模拟长时间操作共享资源,导致cpu易主,产生与时间有关的错误/
printf(“world\n”);
sleep(rand() % 3);
}
return NULL;
}
int main(void)
{
pthread_t tid;
srand(time(NULL));
pthread_create(&tid, NULL, tfn, NULL);
while (1) {
printf("HELLO ");
sleep(rand() % 3);
printf(“WORLD\n”);
sleep(rand() % 3);
}
pthread_join(tid, NULL);
return 0;
} 【mutex.c】
【练习】:修改该程序,使用mutex互斥锁进行同步。
1.定义全局互斥量,初始化init(&m, NULL)互斥量,添加对应的destry
2.两个线程while中,两次printf前后,分别加lock和unlock
3.将unlock挪至第二个sleep后,发现交替现象很难出现。
线程在操作完共享资源后本应该立即解锁,但修改后,线程抱着锁睡眠。睡醒解锁后又立即加锁,这两个库函数本身不会阻塞。
所以在这两行代码之间失去cpu的概率很小。因此,另外一个线程很难得到加锁的机会。
4.main 中加flag = 5 将flg在while中-- 这时,主线程输出5次后试图销毁锁,但子线程未将锁释放,无法完成。
main 中加pthread_cancel()将子线程取消。
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include<stdlib.h>
#include<time.h>
pthread_mutex_t mutex;
void *tfn(void *arg)
{
srand(time(NULL));
while (1) {
pthread_mutex_lock(&mutex);
printf("hello ");
sleep(rand() % 3);
//pthread_mutex_unlock(&mutex);
//pthread_mutex_lock(&mutex);
printf("world\n");
pthread_mutex_unlock(&mutex);
sleep(rand() % 3);
}
return NULL;
}
int main(void)
{
pthread_t tid;
pthread_mutex_init(&mutex,NULL);
srand(time(NULL));
pthread_create(&tid, NULL, tfn, NULL);
int flag=5;
while (flag--) {
pthread_mutex_lock(&mutex);
printf("HELLO ");
sleep(rand() % 3);
//pthread_mutex_unlock(&mutex);
//pthread_mutex_lock(&mutex);
printf("WORLD\n");
pthread_mutex_unlock(&mutex);
sleep(rand() % 3);
}
pthread_cancel(tid);
pthread_join(tid, NULL);
pthread_mutex_destroy(&mutex);
return 0;
}
gcc hello.c -pthread
./a.out
HELLO WORLD
hello world
HELLO WORLD
hello world
HELLO WORLD
HELLO WORLD
hello world
HELLO WORLD
hello world
结束
没有加锁多线程访问共享资源数据错乱
#include<stdio.h>
#include<unistd.h>
#include<pthread.h>
int num=0;
void *fun(void*arg){
int id=*(int*)arg;
int n=10;
while(n-->0){
if(num<20){
sleep(1);
num++;
printf("id=%lu,%d,num=%d\n",pthread_self(),id,num);
}
}
}
int main(){
pthread_t pt[10];
int i,j;
for(i=0;i<10;i++){
pthread_create(&pt[i],NULL,fun,(void*)&i);
usleep(10);
}
for(j=0;j<10;j++){
pthread_join(pt[j],NULL);
}
return 0;
输出大于20
gcc t1.c -pthread
./a.out
id=140178612455168,0,num=1
id=140178604062464,1,num=2
id=140178595669760,2,num=3
id=140178587277056,3,num=4
id=140178578884352,4,num=5
id=140178570491648,5,num=6
id=140178562098944,6,num=7
id=140178553706240,7,num=8
id=140178545313536,8,num=9
id=140178536920832,9,num=10
id=140178604062464,1,num=11
id=140178612455168,0,num=12
id=140178587277056,3,num=13
id=140178595669760,2,num=14
id=140178578884352,4,num=15
id=140178570491648,5,num=16
id=140178562098944,6,num=17
id=140178553706240,7,num=18
id=140178545313536,8,num=19
id=140178536920832,9,num=20
id=140178604062464,1,num=21
id=140178612455168,0,num=22
id=140178587277056,3,num=23
id=140178595669760,2,num=24
id=140178578884352,4,num=25
id=140178570491648,5,num=26
id=140178562098944,6,num=27
id=140178545313536,8,num=28
id=140178553706240,7,num=29
加锁后
#include<stdio.h>
#include<unistd.h>
#include<pthread.h>
#include<time.h>
int num=0;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void *fun(void*arg){
int id=*(int*)arg;
int n=10;
while(n-->0){
pthread_mutex_lock(&mutex);
if(num<20){
usleep(50);
num++;
printf("id=%lu,%d,num=%d\n",pthread_self(),id,num);
}
pthread_mutex_unlock(&mutex);
usleep(100);
}
}
int main(){
pthread_t pt[10];
int i,j;
time_t start;
time(&start);
for(i=0;i<10;i++){
pthread_create(&pt[i],NULL,fun,(void*)&i);
usleep(10);
}
for(j=0;j<10;j++){
pthread_join(pt[j],NULL);
}
time_t end;
time(&end);
double duration= difftime(end,start);
printf("%f\n",duration);
return 0;
}
gcc t2.c -pthread
./a.out
id=140014519871232,0,num=1
id=140014511478528,1,num=2
id=140014519871232,0,num=3
id=140014511478528,1,num=4
id=140014494693120,3,num=5
id=140014511478528,1,num=6
id=140014486300416,4,num=7
id=140014477907712,5,num=8
id=140014519871232,0,num=9
id=140014503085824,2,num=10
id=140014469515008,6,num=11
id=140014390343424,7,num=12
id=140014494693120,3,num=13
id=140014390343424,7,num=14
id=140014511478528,1,num=15
id=140014390343424,7,num=16
id=140014486300416,4,num=17
id=140014477907712,5,num=18
id=140014519871232,0,num=19
id=140014503085824,2,num=20
0.000000