前面两篇给基本概念讲过了,大家有兴趣的可以去看一下:
Linux多线程_神厨小福贵!的博客-CSDN博客进程和线程的区别有哪些呢?进程是资源分配的最小单位,线程是CPU调度的最小单位进程有自己的独立地址空间,线程共享进程中的地址空间进程的创建消耗资源大,线程的创建相对较小进程的切换开销大,线程的切换开销相对较小进程:程序执行的过程叫进程。线程:进程内部的一条执行序列或执行路径,一个进程可以包含多条线程(多线程)!每个进程最少有一个线程,例如下面代码:#include
#include
#include
#include
#include
#include //多线程的创建 等待 退出所需的头文件
int g_index = 1;
void* fun(void* arg)
{
for(int i = 0 ; i < 1000 ; i++)
{
printf(" g_index = %d \n",g_index++);
}
}
int main()
{
pthread_t id[5];
for(int i = 0 ; i < 5 ; i++)
{
pthread_create(&id[i],NULL,fun,NULL);
}
for(int i = 0 ; i < 5 ; i++)
{
pthread_join(id[i],NULL);
}
exit(0);
}
如上代码所示,该代码的初衷是想由主线程创建五个子线程来共同对全局变量g_index进行++的操作,理想中打印出来的结果应该是1 2 3 ...... 5000
那么具体结果是如何呢,下面我们来看一下代码运行的结果:
这是第一次运行::
这是第二次运行:
大家可以看看,仅仅是两次的运行,结果就大不相同,这只是两次的结果,如果多运行几次,那么结果可能千变万化。
我们先来说一下出现这种情况的原因是什么,请看下图:
那么如何解决这种情况呢,信号量和互斥锁
第一个参数是信号量的地址;
第二个参数是释放需要两线程之间共享,这里我们用不到,给个0就好
第三个参数是信号量的初始值
参数就是信号量的地址
那么对于这道题来说,想要让五个子线程打印5000个有序的数来说,需要定义多少个信号量呢?大家好好想想,没思路的话,可以去看看这篇博客:Linux编程题:信号量同步三进程依次打印若干次ABC_神厨小福贵!的博客-CSDN博客
大家是不是以为定义5个信号量,来追着下一个信号量的尾巴,对它进行操作,然后打印吗?
错了(也不是完全错了),上面那种五个信号量适用于进程间的,而在线程中,他们是并发执行的,你要是搞5个信号量的,就是规定了每个线程的打印顺序,完全没必要,我们现在完全不关心谁先打印数字(谁先打印都无所谓的),我们关心的只是多个线程中同时只有一个能进行打印,所以一个信号量足够了,下面来看代码:
#include
#include
#include
#include
#include
#include //信号量操作所需的头文件
sem_t semid; //定义信号量
int g_index = 1;
void* fun(void* arg)
{
for(int i = 0 ; i < 1000 ; i++)
{
sem_wait(&semid); //在g_index++之前进行减一操作,使得其他的线程堵塞
printf(" g_index = %d \n",g_index++);
sem_post(&semid); //在g_index++之后进行加一操作,使得其他的线程得以正常运行
}
}
int main()
{
sem_init(&sem,0,1); //将信号量初始值给1
pthread_t id[5];
for(int i = 0 ; i < 5 ; i++)
{
pthread_create(&id[i],NULL,fun,NULL);
}
for(int i = 0 ; i < 5 ; i++)
{
pthread_join(id[i],NULL);
}
sem_destroy(&semid); //信号量的销毁函数
exit(0);
}
这样的话,我们来看一下运行结果!
这样的话,就让多线程并发执行进行同步!
线程同步指的是当一个线程在对某个临界资源进行操作时,其他线程都不可以对这个资源进行操作,直到该线程完成操作, 其他线程才能操作,也就是协同步调,让线程按预定的先后次序进行运行。
互斥锁可以理解为就是在商场试衣间里面,你进去之后给试衣间上锁,然后其他人就必须等你解锁之后才可以正常使用这个试衣间,你在使用的时候,其他人只能阻塞(等你使用完)!
第一个参数是互斥锁的饿地址
第二个参数是互斥锁的属性,一般置为NULL
参数都是互斥锁的地址
下面来看代码:
#include
#include
#include
#include
#include
int g_index = 1;
pthread_mutex_t mutex; //互斥锁的定义
void* fun(void* arg)
{
for(int i = 0 ; i < 1000 ; i++)
{
pthread_mutex_lock(&mutex); //互斥锁的上锁
printf(" g_index = %d \n",g_index++);
pthread_mutex_unlock(&mutex); //互斥锁的解锁
}
}
int main()
{
pthread_mutex_init(&mutex,NULL); //互斥锁的初始化
pthread_t id[5];
for(int i = 0 ; i < 5 ; i++)
{
pthread_create(&id[i],NULL,fun,NULL);
}
for(int i = 0 ; i < 5 ; i++)
{
pthread_join(id[i],NULL);
}
pthread_mutex_destroy(&mutex);
exit(0);
}
然后代码运行结果和上述的信号量一毛一样:
信号量和互斥锁的代码不难,难的是理解这种思想,因为这是线程,所以在定义信号量的时候,定义一个就够了,因为谁打印出那个数字,我不在乎,五个子线程谁抢到了谁就打印,但是每次只能有一个子线程在打印,互斥锁也是如此,每次只能一个线程去打印,理解了思想,这就可以了!