1,volatile
它所修饰的变量不保留拷贝,直接访问主内存中的。
在 Java 内存模型中,有 main memory,每个线程也有自己的 memory (例如寄存器)。为了性能,一个线程会在自己的 memory 中保持要访问的变量的副本。这样就会出现同一个变 量在某个瞬间,在一个线程的 memory 中的值可能与另外一个线程 memory 中的值,或者 main memory 中的值不一致的情况。一个变量声明为 volatile,就意味着这个变量是随时会被其他线程修改的,因此不能将它 cache 在线程memory 中。
2,synchronized
当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码。
一、当两个并发线程访问同一个对象 objec t中的这个 synchronized(this) 同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。
二、然而,当一个线程访问 object 的一个 synchronized(this) 同步代码块时,另一个线程仍然可以访问该 object 中的非 synchronized(this)同步代码块。
三、尤其关键的是,当一个线程访问 object 的一个 synchronized(this) 同步代码块时,其他线程对 object 中所有其它 synchronized(this) 同步代码块的访问将被阻塞。
四、当一个线程访问 object 的一个 synchronized(this) 同步代码块时,它就获得了这个 object 的对象锁。结果,其它线程对该 object 对象所有同步代码部分的访问都被暂时阻塞。
五、以上规则对其它对象锁同样适用.
区别:
一、volatile 是变量修饰符,而 synchronized 则作用于一段代码或方法。
二、volatile 只是在线程内存和“主”内存间同步某个变量的值;而 synchronized 通过锁定和解锁某个监视器同步所有变量的值。显然synchronized 要比 volatile 消耗更多资源。
三、volatile 不能保证操作的原子性。synchronized 可以保证操作的原子性。
那么请参考如下:
volatile 不能保证操作的原子性。synchronized 可以保证操作的原子性。我认为这是他们最大的区别。
此外 volatile 是变量修饰符,而 synchronized 是要修饰一段代码或者方法
那么volatile是干什么的呢?
volatile是变量修饰符。被它修饰的变量不会在线程中保留备份(注:可以这么理解,但是其内部机制应该还是保留了备份的,只不过是通过特殊的机制实时的将线程中变量的值更新到i)。这样就不会出现上述线程A B 和主内存的值不一样的情况。
但是注意:volatile并不能保证操作的原子性。即使只是i++,实际上也是由多个原子操作组成:read i; inc; write i,假如多个线程同时执行i++,依然可能出现写入脏数据的情况。它只不过是保证各个线程操作的是同一块儿内存而已。
synchronized 为什么能保证操作的原子性呢?
这得从它的工作机制说起,很明显 synchronized 能够保证被它修饰的一段代码同一个时刻只被同一个线程执行。
事实上它同步代码的过程也在同步内存。
假如有如下代码:
public class Test implements Runnable{
private int i=1;
public void run(){
operate();
}
public synchronized void operate(){
i = 2;
}
}
当线程A执行方法operate的时候将进行如下步骤:
1.线程请求this的锁,如果锁被其他的线程占用就进入阻塞状态直到锁被释放。
2.线程内存中缓存的数据被清除,从主内存中read/load读入最新的值。
3.synchronized内的代码块被执行,在此执行过程中其对应的主内存不会被其他的线程使用。
4.执行完毕释放锁。
水平有限,若有问题请留言交流!
互相学习,共同进步 :)转载请注明出处谢谢!