线程同步

本文深入探讨了线程同步机制,包括信号量、互斥锁、条件变量和读写锁的使用方法。通过具体示例代码,展示了如何利用这些机制确保多线程环境下数据的一致性和安全性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

线程同步:信号量  互斥锁  条件变量      读写锁

线程安全:

                1、同步

                2、线程安全的函数

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<assert.h>
#include<pthread.h>
#include<semaphore.h>
//strtok_r 可重入的函数
void* thread_fun(void *arg)
{

    char str[]={"a b c d e f g h k l"};
    char *ss=NULL;
    char *s=strtok_r(str," ",&ss);
    //char *s=strtok(str," ");//不安全的线程函数
    while(s !=NULL)
    {
	printf("s=%s\n",s);
	sleep(1);
	s=strtok_r(NULL," ",&ss);
	//s=strtok(NULL," ");
    }
    
}


int main()
{
    pthread_t id;
    
    
	pthread_create(&id,NULL,thread_fun,NULL);//创建线程,已经被创建出来的线程和主线程并发
	char arr[]={"1 2 3 4 5 6 7 8 9"};
	char *dd=NULL;
	char *p=strtok_r(arr," ",&dd);
	//char *p=strtok(arr," ");

	while(p!=NULL)
	{
	    printf("p=%s\n",p);
	    sleep(1);
	    p=strtok_r(NULL," ",&dd);
	    //p=strtok(NULL," ");
	}
    

    

	pthread_join(id,NULL);
    
    

    exit(0);

}

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<assert.h>
#include<pthread.h>



pthread_mutex_t mutex;//定义互斥锁
//sem_t sem;//定义信号量

void *thread_fun(void* arg)

{
    int i=0;
    for(;i<5;i++)
    {
	//sem_wait(&sem);//p操作 获取资源
	pthread_mutex_lock(&mutex);//上锁
	write(1,"B",1);
	int n =rand()%3;
	sleep(n);
	write(1,"B",1);
	//sem_post(&sem);//v操作 释放资源
	pthread_mutex_unlock(&mutex);//解锁
	n=rand()%3;
	sleep(n);
    }
}
int main()
{
    pthread_t id;//
    //sem_init(&sem,0,1);初始化信号量
    pthread_mutex_init(&mutex,NULL);//初始化互斥锁
    pthread_create(&id,NULL,thread_fun,NULL);//

    int i=0;
    for(;i<5;i++)
    {
	//sem_wait(&sem);
	pthread_mutex_lock(&mutex);
	write(1,"A",1);
	int n =rand()%3;
	sleep(n);
	write(1,"A",1);
	//sem_post(&sem);
	pthread_mutex_unlock(&mutex);
	n=rand()%3;
	sleep(n);
    }
    pthread_mutex_destroy(&mutex);
    pthread_join(id,NULL); //等待子线程结束,否则主线程结束后 直接结束程序
    exit(0);
}

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<assert.h>
#include<pthread.h>
#include<semaphore.h>

pthread_mutex_t mutex;
pthread_cond_t cond;//条件变量

void *fun1(void *arg)
{
    char *s=(char*)arg;
    while(1)
    {
	pthread_mutex_lock(&mutex);
	pthread_cond_wait(&cond,&mutex);
	pthread_mutex_unlock(&mutex);

	printf("fun1 read:%s\n",s);
	if(strncmp(s,"end",3)==0)
	{
	    break;
	}
    }
}
void *fun2(void *arg)
{
    char *s=(char*)arg;
    while(1)
    {
	pthread_mutex_lock(&mutex);
	pthread_cond_wait(&cond,&mutex);
	pthread_mutex_unlock(&mutex);

	printf("fun2 read:%s\n",s);
	if(strncmp(s,"end",3)==0)
	{
	    break;
	}
    }
}
int main()
{
    pthread_t id[2];
    char buff[128]={0};
    pthread_cond_init(&cond,NULL);
    pthread_mutex_init(&mutex,NULL);
    pthread_create(&id[0],NULL,fun1,(void *)buff);
    pthread_create(&id[1],NULL,fun2,(void *)buff);
    while(1)
    {
	fgets(buff,128,stdin);
	if(strncmp(buff,"end",3)==0)
	{
	    pthread_mutex_lock(&mutex);
	    pthread_cond_broadcast(&cond);//广播式唤醒
	    pthread_mutex_unlock(&mutex);

	    break;
	}
	else
	{

	    pthread_mutex_lock(&mutex);
	    pthread_cond_signal(&cond);//一次只能有一个线程被唤醒
	    pthread_mutex_unlock(&mutex);
	}
    }

    pthread_join(id[0],NULL);
    pthread_join(id[1],NULL);
    exit(0);



}

 ps    -eLf 可以显示系统所有进程的线程

strace(跟踪系统调用)

ltrace(跟踪程序中执行所调用的函数)在当前路径

fork、vfork、clone都是通过do-fork实现,只不过传入的参数不同

linux下没有真正的线程,系统没有专门创建线程的方法,由多个进程共享一块地址空间模拟得到

纯粹的用户级线程:由用户应用程序创建的线程,有关线程管理的所有工作都由应用程序完成,内核意识不到线程的存在

                                当一个用户级现成本执行一个系统调用时,不仅这个线程会阻塞,进程中的所有线程都会被阻塞

纯粹的内核级线程:线程的创建、调度和管理全部由操作系统内核负责。

                                相比纯粹的用户级进程,用户级线程的线程切换需要少量的机器指令,而内核级线程需要完整的上下文切换,修改内存映像,使高速缓存失效。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值