public class ThreadDemo7{ //structs2线程不安全 共享变量 //n++ 复合操作 对于volatile修饰的变量不安全 //原子操作 int value; //让方法变成一个同步的方法 public synchronized int nextValue(){ return value ++; } public static void main(String[] args){ ThreadDemo7 t1 = new ThreadDemo7(); new Thread(new Runnable() { @Override public void run() { while (true){ System.out.println(t1.nextValue() + " " + Thread.currentThread().getName()); } } }).start(); new Thread(new Runnable() { @Override public void run() { while (true){ System.out.println(t1.nextValue() + " " + Thread.currentThread().getName()); } } }).start(); new Thread(new Runnable() { @Override public void run() { while (true){ System.out.println(t1.nextValue() + " " + Thread.currentThread().getName()); } } }).start(); } }
public class ThreadDemo7_1 { private static volatile int num; //使用countDownLatch来等待使线程执行完 public static CountDownLatch countDownLatch = new CountDownLatch(30); //由于n++是复合操作,所以并不能保证线程安全 //public synchronized int NextValue(){ public int NextValue(){ return num ++; } public static void main(String[] args){ ThreadDemo7_1 t1 = new ThreadDemo7_1(); for(int i=0;i<30;i++){ new Thread(new Runnable() { @Override public void run() { for(int j=0;j<10000;j++){ t1.NextValue(); } countDownLatch.countDown(); } }).start(); } try{ countDownLatch.await(); }catch (InterruptedException e){ e.getMessage(); } System.out.println(num); } }
public class ThreadDemo7_2 { private static AtomicInteger num = new AtomicInteger(); //使用countDownLatch来等待使线程执行完 public static CountDownLatch countDownLatch = new CountDownLatch(30); public static void main(String[] args){ ThreadDemo7_1 t1 = new ThreadDemo7_1(); for(int i=0;i<30;i++){ new Thread(new Runnable() { @Override public void run() { for(int j=0;j<10000;j++){ num.incrementAndGet(); //原子性的num++,通过cas方式 } countDownLatch.countDown(); } }).start(); } try{ countDownLatch.await(); }catch (InterruptedException e){ e.getMessage(); } System.out.println(num); }
概念解析
并发机制依赖于JVM的实现和CPU的指令
1. volatile一般在多线程中使用,保证共享变量的可见性,解决并发带来的问题
可见性意思就是一个线程修改另外一个线程可以看到修改后的值,通过排它锁单独获得这个变量
volatile执行成本低,因为不会引起线程上下文的切换和调度
synchronized是重量级锁
2. volatile深层理解
有volatile变量修饰的共享变量进行读写操作的时候会多出第二行汇编代码
lock前缀的指令在多核处理器下会引发两件事情:
1)lock前缀指令会引起处理器缓存回写到内存
2)这个写回内存的操作会使在其他CPU里缓存了该内存地址的数据无效
3. synchronized实现同步的基础:java中的每一个对象都可以作为锁
具体表现如下:
1)对于普通同步方法,锁是当前实例对象
2)对于静态同步方法,锁是当前类的class对象
3)对于同步方法块,锁是synchronized括号里配置的对象
当一个线程视图访问同步代码块时,它首先必须得到锁,退出或抛出异常时必须释放锁
Synchronized在JVM里的实现原理:JVM基于进入和退出Monitor对象来实现方法同步和代码块同步
2. 无锁,偏向锁,轻量级锁,重量级锁