线程同步:信号量 互斥锁 条件变量 读写锁
线程安全:
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下没有真正的线程,系统没有专门创建线程的方法,由多个进程共享一块地址空间模拟得到
纯粹的用户级线程:由用户应用程序创建的线程,有关线程管理的所有工作都由应用程序完成,内核意识不到线程的存在
当一个用户级现成本执行一个系统调用时,不仅这个线程会阻塞,进程中的所有线程都会被阻塞
纯粹的内核级线程:线程的创建、调度和管理全部由操作系统内核负责。
相比纯粹的用户级进程,用户级线程的线程切换需要少量的机器指令,而内核级线程需要完整的上下文切换,修改内存映像,使高速缓存失效。