168-Linux多线程(下)

如何查看线程id?
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

实现三个线程分别打印ABC(有序)

在这里插入图片描述
代码实现如下:

在这里插入图片描述
在这里插入图片描述
运行结果如下:
在这里插入图片描述

多线程中进行fork会发生什么情况?

注意:不管在哪个线程打印pid,pid的值都是整个进程的id号。
在这里插入图片描述
运行结果如下
在这里插入图片描述
1、创建一个线程,有两条路径,一条是主线程,一条是子线程,在主线程加入fork();
在这里插入图片描述
运行结果如下
在这里插入图片描述
我们可以得知:父进程的id号为4952,子进程的id号为4954,父进程的id号在主线程和子线程都打印了,子进程的id号只在主线程打印
4953就是子线程的id号
我们发现fork之后,子进程只有一条路径

2、创建一个线程,有两条路径,一条是主线程,一条是子线程,在子线程加入fork();
在这里插入图片描述
运行结果如下
在这里插入图片描述
我们得知:父进程的id号为4976,子进程的id号为4978
子进程的id号只在子线程打印,父进程的id号在主线程和子线程都打印

总结:
不管父进程有多少条执行路径,fork后的子进程只有一条执行路径,子进程只启动fork所在的那条执行路径!

多线程fork,引入互斥锁

在这里插入图片描述
在这里插入图片描述

运行结果如下:
在这里插入图片描述
子线程打印锁了,锁住和解锁了,子进程一直没有得到锁,阻塞住,结束不了,父进程也不能退出

为什么子线程释放锁了,子进程依然无法得到锁

结论:fork之后,父进程和子进程用的不是同一个锁!父进程修改锁的状态,子进程依然无法进行加锁。fork之后,子进程复制了父进程的资源,同时也把锁复制过来,这把锁的状态取决于复制的那一刻父进程锁的状态。
sleep(1);子线程加锁成功,fork之后子进程拿到的锁是已经加锁的状态,再加锁,阻塞住。

解决方法
不能一上来就unlock,表面上看我们是在进行加锁和解锁,实际上加锁和解锁背后是对临界资源的控制,当它加了锁,说明临界资源在被使用,没有依据的情况下去解锁是不可取的。
fork之后 并不确定锁的状态

我们就挑一个空闲的时间,没人用锁的时候,再去进行fork去控制

加锁能成功,说明没人用锁。
然后fork之后在父子进程中分别进行解锁就可以了

在这里插入图片描述

第一个参数是在执行fork之前执行的
第二个参数是fork以后在父进程进行的
第三个参数是fork以后在子进程进行的

在这里插入图片描述
等父进程中锁没人用的时候再进行fork,所以38行的fork会延迟

运行结果如下
在这里插入图片描述

在这里插入图片描述

条件变量的使用

条件变量提供了一种线程间的通知机制:当某个共享数据达到某个值的时候,唤醒等待这个共享数据的线程
在这里插入图片描述

#include <pthread.h>

int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *attr);
//初始化条件变量

int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
//等待条件变量的值达到某个条件//阻塞

int pthread_cond_signal(pthread_cond_t *cond);
//唤醒单个线程

int pthread_cond_broadcast(pthread_cond_t *cond); 
//唤醒所有等待的线程

int pthread_cond_destroy(pthread_cond_t *cond);
//销毁条件变量

使用条件变量就要用到互斥锁
因为我们要添加到条件变量的队列中,在添加的过程中,不能让其他访问。
防止两个人同时把自己添加到条件变量队列上

fun线程先加锁操作,另一个线程加锁失败。
fun线程先加锁操作,然后添加队列的过程中,添加完,解个锁,阻塞住,加进去之后其他线程才能添加。然后加个锁,出队列,出队列以后我们再解锁。就是wait阻塞住,等待全局变量可用,主线程通知变量可用了,wait解除阻塞。
唤醒的时候,必须是没人入出队列。唤醒之前 加个锁,说明其他人没人用锁没人进出队列
在这里插入图片描述
在这里插入图片描述
运行结果如下
在这里插入图片描述

在这里插入图片描述
唤醒的是哪个线程我们不清楚

该进代码
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

运行结果如下
在这里插入图片描述

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <unistd.h>
#include <string.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);
}

运行结果如下
在这里插入图片描述

最多可以创建多少个线程?

32位系统下是0-4G,用户可以使用下3G,内核使用上面那1G,不管多少线程,代码段数据段是共享的,线程栈不共享
3G除以一个线程大小,大概可以算出理论上创建多少个线程
sudo设置线程栈的大小
在这里插入图片描述
线程栈的大小10M
线程数目4096
在这里插入图片描述

期望创建2000个
在这里插入图片描述

3G/10M 300个左右的线程

在这里插入图片描述
栈缩小一半
可以创建约600个线程
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
因为系统本身还运行着一些进程

要防止栈溢出,或者设置太大

深度系统可以创建1万多个线程

读写锁

#include <pthread.h>

int pthread_rwlock_init(pthread_rwlock_t *rwlock, pthread_rwlockattr_t *attr);

int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);

int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);

int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);

int pthread_rwlock_destroy(pthread_rwlock_t *rwlock)

猜你喜欢

转载自blog.csdn.net/LINZEYU666/article/details/113616343