在看线程安全之前要明白临界资源的概念。 临界资源就是一次只允许一个进程使用的资源。就像厕所一样,一次只能一个人用。因此需要 合理控制对于临界资源的访问操作,使得程序可以正常运行,这就是线程安全。
线程安全分为两部分:同步与互斥。
一、对互斥的理解
互斥是什么?
互斥是为了保证程序运行的安全性。一个程序在使用临界资源时,其他线程就不可以使用,只有等到其他线程使用完毕才可以去使用。就像厕所一样,只有一个人用完了,第二个人才可以进去,不然只能在外面等。
如何实现互斥?
(1)通常使用互斥锁来实现线程的互斥。这个互斥锁其实就是一个0/1计数器,0代表临界资源正在被使用,1代表临界资源是空闲的。
(2)如果A线程要访问临界资源,此时就去看一下互斥锁是不是已经被锁上了,如果被锁上说明这个临界资源正在被使用。如果临界资源没有被锁上,说明此时临界资源是空闲的,A线程可以去使用。使用前A线程需要给临界资源加锁,A线程加的锁只有自己才可以打开锁,其他线程是打不开的。
(3)这就像是A去上厕所,然后把门反锁,这样其他人就进不去,也打不开锁,只有A自己才可以把锁打开。所以说互斥锁其实和现实中的锁是很像的。
(4)访问临界资源的时候,如果可以访问则加锁,将资源标记为不可访问状态,然后正确返回。如果资源此时不可以访问,那么就会阻塞或者报错返回。
(5)要实现互斥的话,最重要的是大家必须使用同一把锁。就像自己家的门,家里人都有钥匙,但是锁只有一把。如果一人一把锁,那就乱套了。因此这也证明了互斥锁也是一个临界资源,因此对互斥锁的操作一定要保证是安全的。
二、对同步的理解
同步是什么?
同步是为了保证程序运行的合理性。如果有多个线程都要访问同一个临界资源,那么肯定要规划好谁先谁后的问题,不然一窝蜂地跑去使用临界资源很容易出问题。如果好几个人要使用厕所,但厕所只有一个,这个时候就要排个队,让所有人都能合理的使用厕所,不至于让几个人去抢厕所。
如何实现同步?
(1)同步就是让访问资源变得更加合理。比如:实现互斥时,为了让资源访问变得安全,我们在访问前给资源加锁,访问后解锁。但是什么时候加锁,什么时候解锁,如何把握这个时间点,就是同步的问题了。
(2)而我们使用条件变量来进行同步,条件变量里面包含了许多的工具,我们需要做的事情就是规定什么时候去使用什么工具来保证资源访问的合理性。