5.线程与并发同步-pthread_mutex_t加锁步骤测试

看如下程序:该程序是非常典型的,由于共享、竞争而没有加任何同步机制,导致产生于时间有关的错误,造成数据混乱:
#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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值