多个线程可以读一个变量,只有一个线程可以对这个变量进行写,到底要不要加锁
12402023-08-21
大家好,如果您还对多个线程可以读一个变量,只有一个线程可以对这个变量进行写,到底要不要加锁不太了解,没有关系,今天就由本站为大家分享多个线程可以读一个变量,只有一个线程可以对这个变量进行写,到底要不要加锁的知识,包括多线程为什么不建议加锁的问题都会给大家分析到,还望可以解决大家的问题,下面我们就开始吧!
本文目录
先说结论:不必要
如果不需要可见性,什么都不需要加如果需要保证可见性,则需要加volatile关键字。这里可以加锁,但是没必要,对性能有影响下面简单解释下原因:
加锁是因为操作不是原子性的,以i++这个操作来解释,看下面两张图。
i++这个操作需要
先将i的值从内存中读出来然后加1最后写回去看上面第二张图,能很清楚的理解流程吧?
加锁就是保证上面的三步是一个原子操作。
回到问题,这里只有一个线程写,实际没有竞争,所以没必要加锁。
但是,看第一张图,因为有主内存和本地内存的存在
线程先写入本地内存然后刷入主内存其它内存同步主内存到工作内存然后从工作内存中读取一个线程写入后,不能保证其它线程立即看到,这就是可见性问题。
加了volatile关键字后,会强制操作后同步工作内存和主内存,保证其它线程立刻看到。
一:互斥与同步 互斥:一个公共资源同一时刻只能被一个进程或线程使用,多个进程或线程不能同时使用公共资源。 同步:两个或两个以上的进程或线程在运行过程中协同步调,按预定的先后次序运行。 解决方法:互斥锁,条件变量,读写锁,自旋锁,信号量(互斥与同步) 二:互斥锁(同步) 互斥锁是一种简单的加锁的方法来控制对共享资源的访问,互斥锁只有两种状态,即上锁(lock)和解锁(unlock)。 特点:唯一性,原子性,非繁忙等待 三:条件变量(同步) 条件变量是用来等待而不是用来上锁的。条件变量用来自动阻塞一个线程,直到某特殊情况发生为止。适合多个线程等待某个条件的发生,不使用条件变量,那么每个线程就不断尝试互斥锁并检测条件是否发生,浪费系统资源。 四:读写锁(同步) 三种状态:读模式下加锁状态、写模式加锁状态、不加锁状态 【读写锁的特点】: 如果有其它线程读数据,则允许其它线程执行读操作,但不允许写操作; 如果有其它线程写数据,则其它线程都不允许读、写操作。 【读写锁的规则】: 1:如果某线程申请了读锁,其它线程可以再申请读锁,但不能申请写锁; 2:如果某线程申请了写锁,其它线程不能申请读锁,也不能申请写锁。 读写锁适合于对数据结构的读次数比写次数多得多的情况。 五:自旋锁(同步)#include<semaphore.h> 自旋锁与互斥量功能一样,唯一一点不同的就是互斥量阻塞后休眠让出cpu,而自旋锁阻塞后不会让出cpu,会一直忙等待,直到得到锁。自旋锁在用户态使用的比较少,在内核使用的比较多!自旋锁的使用场景:锁的持有时间比较短,或者说小于2次上下文切换的时间。 六:信号量(同步与互斥) 信号量本质上是一个非负的整数计数器,它被用来控制对公共资源的访问。 编程时可根据操作信号量值的结果判断是否对公共资源具有访问的权限,当信号量值大于0时,则可以访问,否则将阻塞。PV原语是对信号量的操作,一次P操作使信号量减1,一次V操作使信号量加1。
看情况,如果有多线程安全问题,就需要加
你所说的父线程是指A线程在方法中开启了B线程,A为B的父吧?你可以理解为,A在开启B以后,A和B就是两个独立的线程了,访问同一个变量存在不同步的风险,那么显然如果有需要,是要在访问这个变量的方法中加锁的
如果你还想了解更多这方面的信息,记得收藏关注本站。