0
点赞
收藏
分享

微信扫一扫

解决共享资源竞争

柠檬果然酸 2023-06-30 阅读 100

解决共享资源竞争

基本上所有的并发模式在解决线程冲突问题的时候,都是采用序列化访问共享资源的方案。这意味着在给定时刻只允许一个任务访问共享资源。通常这是通过在代码前面加上一条锁语句来实现的,这就使得在一段时间内只有一个任务可以运行这段代码。因为锁语句产生了一种互相排斥的效果,所以这种机制常常称为互斥量
线程调度机制并不是确定性的。
Java以提供关键字synchronized的形式,为防止资源冲突提供了内置支持。当任务要执行被synchronized关键字保护的代码片段的时候,它将检查锁是否可用,然后获取锁,执行代码,释放代码。
共享资源一般是以对象形式存在的内存片段,但也可以是文件、输入/输出端口,或者是打印机。要控制对共享资源的访问,得先把它包装进一个对象。 然后把所有要访问这个资源的方法标记为synchronized。如果某个任务处于一个对标记为synchronized的方法的调用中,那么在这个线程从该方法返回之前,其他所有要调用类中任何标记为synchronized方法的线程都会阻塞。

当对象上调用其任意synchronized的时候,此对象都被加锁。如果某个任务对对象调用了f(),对于同一个对象而言,就只能等到f()调用结束并释放了锁之后,其他任务才能调用f()和g()。所以,对于某个特定对象来说,其所有synchronized方法共享同一个锁,这可以被用来防止多个任务同时访问被编码为对象内存。

注意:在使用并发时,将域设置为private是非常重要的,否则,synchronized关键字就不能防止其他任务直接访问域,这样就会产生冲突。
一个任务可以多吃获得对象的锁。如果一个方法在同一对象上调用了第二个方法,后缀又调用了同一个对象上的另一个方法,就会发生这种情况。JUM负责跟踪对象被加锁的次数,如果一个对象被解锁(即锁被完全释放),其计数渐变为0.在任务第一次给对象加锁的时候,计数变为1,每当这个相同的任务在这个对象上获得锁时,计数都会递增,显然,只有首先获得了锁的任务才能允许继续获取多个锁。每当任务离开一个synchronized方法,计数递减,当计数为零的时候,锁被完全释放,此时别的任务就可以使用此资源。
针对每个类,也有一个锁,所以synchronized static方法可以在此类的范围内防止对static数据的并发访问。
如果你正在写一个变量,它可能接下来将被另一个线程读取,或者正在读取一个上一个已经被另一个线程写过的变量,那么你必须使用同步,并且,读写线程都必须用相同的监视器锁同步。
如果在你的类中有超过一个方法,在处理临界数据,那么你必须同步所有相关的方法。如果只同步一个方法,那么其他方法将会随意地忽略这个对象锁,并可以在无任何惩罚的情况下被调用。这是很重要的一点:每个访问临界共享资源的方法都必须被同步,否则他们就不会正确地工作。

举报

相关推荐

0 条评论