波奇学Linux:线程的同步和互斥

创建多线程

线程可以访问全局变量

线程的局部存储

__thread int a;

a在线程局部存储,相当于每个线程都拷贝一份

__thread 局部存储只能用于内置类型,不能用于自定义类型 

 线程分离,结束后不用等待,自己释放资源

int pthread_detach(pthread_t thread);

线程分离可能导致进程不阻塞等待,提前结束,而使得线程也结束

线程分离可以父线程分离或者子线程分离

线程的互斥问题

多线程共同访问数据时,造成数据不一致问题。

模拟抢票代码

#include<iostream>
#include<vector>
#include<pthread.h>
#include<string>
#include<unistd.h>
using namespace std;

#define NUM 4
int tickets=1000;
// 用多线程 模拟一轮抢票
//代表一个线程
class threadData
{
public:
    threadData(int number)
    {
        threadname="thread-"+to_string(number);
    }
public:
    string threadname;
};
void* getTicket(void* args)
{
    threadData* td=static_cast<threadData*>(args);
   
   while(true)
   {
    if(tickets>0)
    {
        usleep(1000);
        printf("who=%s, get a ticket: %d\n",td->threadname.c_str(),tickets);
        tickets--;
    }
    else
    {
        break;
    }
   }
    return nullptr;
}
int main()
{
    //线程tid
    vector<pthread_t> tids;
    // 线程数据
    vector<threadData*> thread_datas;
    for(int i=1;i<=NUM;i++)
    {
        pthread_t tid;
        threadData* td=new threadData(i);
        thread_datas.push_back(td);
        // 传输数据,当扩展字段时可以直接扩展类变量
        pthread_create(&tid,nullptr,getTicket,thread_datas[i-1]);
        tids.push_back(tid);
    }
    for(auto thread:tids)
    {
        pthread_join(thread,nullptr);
        
    }
    for(auto td:thread_datas)
    {
        delete td;
    }
    return 0;
}

对一个全局变量进行变量进行多线程并发 --/++不是安全的。

寄存器不等于寄存器的内容

线程在执行时,将共享数据,加载到cpu的本质是把数据的内容,变成自己的上下文,给自己单独拿了一份。

--操作分为三步

数据从内存加载到寄存器

数据修改

数据从寄存器加载到内存

假设初始值是10,当线程1,处于第一步切换到线程2,3,4...,完成了三步,内存的值为1,但是又切换回线程1,线程恢复上下文的值为10,修改后内存的值又为9。

解决方法:对共享数据的访问,保证任何时候只有一个执行流

加锁的本质就是时间换资源,加锁的表现就是线程对于临界区代码的串行执行

纯互斥场景,如果锁分配不合理,容易导致其他线程的饥饿问题,竞争不到锁资源

解决方法:让所有的线程获取锁资源按照一定的顺序

不能立马重新申请锁,插入排队队列的末尾。

锁本身就是临界资源,申请锁和缩放锁是原子的

在线程被切出去,是持有锁被切走的。可以进行线程切换

全局变量定义锁:不用init和释放

pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER

锁的原理

原子:一条汇编语句就是原子的

exchange或者swap指令能交换寄存器和内存内容

lock: movb $0 %al 将eax寄存器的值变空

xchgb %al, mutex 交换锁和寄存器的值

if(al 寄存器内容>0)

{

return 0;

} else 挂起等待

goto lock;

交换的本质是把数据1交换到线程的硬件上下文

只有一个1,多个0

movb $1 mutex 唤醒等待的mutex的线程

函数不可重入,多线程可能出现问题,可重入,不会出现多线程安全问题

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值