
Java之线程并发同步——synchronized方法总结
我们知道,多线程存在着数据安全问题。在并发线程中,一个对象同时可以被多个线程访问,修改等。比如购买火车票的例子,若只剩下最后一张火车票,但此时同时有多个线程正在访问该数据,那么如果不加约束,那么这些线程都将成功购得同一张火车票,最后导致系统中火车票剩余数量变为负数!
以下是一个不加约束的示范:
以下是运行的结果(由于在这CPU调度调度是随机的,所以每次结果都有不同,在此我特意选了一个存在问题的结果展示)
从上面的结果我们发现了问题,第2张票同时被两个人取到。这里的原因就在于,每个线程都是在自身的工作内存中进行交互,这里小张和小明都看到了第2张票,于是都将第2张信息拷入自身内存进行处理,从而都获得了第2张票。所以要解决这个数据安全问题,我们需要对线程进行排队(队列+锁)处理,即实现线程的同步!
接下来,介绍同步。
首先是方法的同步(同步方法,即synchronized方法)。
简单来说,synchronized方法就是控制对“对象”的访问,每一个对象都对应着一把锁,而每一个synchronized方法都必须获得调用该方法的对象的锁才能执行,否则线程阻塞。而synchronized方法一旦执行,就独占该锁,使得其他需要获取该锁线程阻塞,直到该方法返回后才会释放其所占的锁。而后其他线程可以重新抢夺该锁,继续执行。
为了更好示范同步,这里我将之前的代码更改:
面的代码仅仅是对之前进行了修改,但本质不变,其仍存在数据安全问题。
但是我们在这里可以使用synchronized方法解决这个问题,synchronized方法使用非常简单,以下是使用synchronized方法后的代码:
执行结果如下图,数据安全问题被顺利解决:
最后synchronized方法总结一下:
synchronized 方法其实就是线程在使用该方法操作对象时,会获取该对象的锁,将其锁住,而其他线程同样使用synchronized 方法的时候因为无法获取该锁(一个对象只有一个锁),因此只能陷入阻塞状态,直到第一个获取该锁的synchronized 方法释放该锁!
不过synchronized方法只能锁住一个固定的对象(this对象),因此当我们需要锁住其他对象的时候,我们需要利用到同步块。
————————————————
版权声明:本文为「小白说java」的原创文章
