java多线程什么时候必须同步?如何同步?

BSO 2020-11-03 16:09:27 java常见问答 3620

上次已经为大家介绍过java多线程的同步与异步的主要内容了,今天再来简述一些与之相关的内容,也就是java多线程什么时候必须同步以及如何同步?一起来看看吧。

首先,我们需要知道的是,要跨线程维护正确的可见性,只要在几个线程之间共享非final变量,就必须使用synchronized(或volatile)以确保一个线程可以看见另一个线程做的更改。

为了在线程之间进行可靠的通信,也为了互斥访问,同步是必须的。这归因于java语言规范的内存模型,它规定了:一个线程所做的变化何时以及如何变成对其它线程可见。

因为多线程将异步行为引进程序,所以在需要同步时,必须有一种方法强制进行。

例如:如果2个线程想要通信并且要共享一个复杂的数据结构,如链表,此时需要确保它们互不冲突,也就是必须阻止B线程在A线程读数据的过程中向链表里面写数据(A获得了锁,B必须等A释放了该锁)。

为了达到这个目的,java在一个旧的的进程同步模型——监控器(Monitor)的基础上实现了一个巧妙的方案:监控器是一个控制机制,可以认为是一个很小的、只能容纳一个线程的盒子,一旦一个线程进入监控器,其它的线程必须等待,直到那个线程退出监控为止。

通过这种方式,一个监控器可以保证共享资源在同一时刻只可被一个线程使用。这种方式称之为同步。(一旦一个线程进入一个实例的任何同步方法,别的线程将不能进入该同一实例的其它同步方法,但是该实例的非同步方法仍然能够被调用)。

同步和多线程关系:没多线程环境就不需要同步;有多线程环境也不一定需要同步。

锁提供了两种主要特性:互斥(mutual exclusion) 和可见性(visibility)。

互斥,即一次只允许一个线程持有某个特定的锁,因此可使用该特性实现对共享数据的协调访问协议,这样,一次就只有一个线程能够使用该共享数据。

可见性要更加复杂一些,它必须确保释放锁之前对共享数据做出的更改对于随后获得该锁的另一个线程是可见的 —— 如果没有同步机制提供的这种可见性保证,线程看到的共享变量可能是修改前的值或不一致的值,这将引发许多严重问题

总而言之,为了防止多个线程并发对同一数据的修改,所以需要同步,否则会造成数据不一致(就是所谓的:线程安全。如java集合框架中Hashtable和Vector是线程安全的。我们的大部分程序都不是线程安全的,因为没有进行同步,而且我们没有必要,因为大部分情况根本没有多线程环境)。

以上就是关于java多线程什么时候必须同步以及如何同步的主要内容了。具体的知识还是比较复杂的。如果你对java知识感兴趣,想要了解更多java常见问题,敬请关注奇Q工具网。

推荐阅读:

java多线程同步ThreadLocal类,实例分享

java多线程同步之重入锁,详细解析

java多线程同步,Volatile详解