阻塞调用并不能保证同步性,因为阻塞调用仅仅只能保证当前线程等待其他线程运行完之后再运行,但是其他线程之间的同步性则不能保证。
保证同步性:
Synchronize
Lock
Volatile(保证一部分的同步性)
Volatile:
对于除double和long之外的其他基本数据的简单操作,可以保证原子性。但是,对于double和long数据而言,JVM将读取和写入当做两个分离的32位操作来执行。volatile关键字能够保证double和long数据的简单操作的原子性,如简单的赋值和返回操作的原子性。但是注意对于自增是不能保证原子性的。
除了保证double和long数据的简单操作的原子性之外,volatile还能够保证数据的可视性。如果你将一个域声明为volatile,那么只要对这个域进行产生了写操作,那么所有的读操作就都可以看到这个修改。即便是用了本地缓存,情况也是如此。Volatile域会立即被写入到主存中,而读操作就发生在主存中。如果多个线程修改或者读取同一个变量,那么可以将这个变量声明为volatile。但是当一个域的值依赖于它之前的值时(如自增),volatile就无法工作了。如果某个域的值受到其他域的值的限制,那么volatile也无法工作。例如Range类的lower和upper边界就必须遵循lower<=upper的限制。
必须说明的是,volatile只是保证了一部分的同步性,在进行同步的时候,你的第一选择应该是使用synchronized关键字,这是最安全的额方式,而尝试其他的任何方式都是有风险的。