2.3其它方法
为了实现变量在多个线程间可见。使得线程从公共堆栈中获取变量,而不是线程私有数据栈。
JVM 在 -sever 模式时为了线程运行效率,线程一直在私有堆栈中获取变量值,而主线程的变量是存储在公共堆栈中,解决这种可见性问题,可以使用 volatile 。
volatile 与 synchronized 的比较:
-
volatile 保证可见性但不保证原子性(致命缺点),synchronized 保证原子性但不保证可见性。
-
volatile 只能修饰变量。
-
volatile 不发生阻塞,synchronized 会阻塞。
多线程使用原子操作访问共享资源时,不需要锁也可保证线程安全(多线程访问同一资源时,不会出现脏读或写失败)。
以下代码,多个线程竞争地访问同一个对象中的 count , 使用原子操作保证了线程安全。
-
CountService.java
public class CountService extends Thread{ private AtomicInteger count = new AtomicInteger(0);//原子类 @Override public void run(){ for (int i = 0; i < 1000; i++){ System.out.println(Thread.currentThread().getName() + ":" +count.incrementAndGet());//incrementAndGet 方法是原子操作 } } }
-
Run.java
public class Run { public static void main(String[] args) { CountService countService = new CountService(); Thread t1 = new Thread(countService); t1.setName("t1"); t1.start(); Thread t2 = new Thread(countService); t2.setName("t2"); t2.start(); Thread t3 = new Thread(countService); t3.setName("t3"); t3.start(); } }
方法间的调用不是原子的(调用多个原子操作,不具有原子性,线程间会出现抢占),需要使用 synchronized 来保证线程安全。