/** * Created by yxl on 2019-07-06. */ public class TestVolatile { public static void main(String[] args) { ThreadDemo td =new ThreadDemo (); new Thread(td).start (); while (true){ synchronized (td){ if(td.isFlag ()){ System.out.println ("---" ); break; } } } } } class ThreadDemo implements Runnable{ private boolean flag=false; @Override public void run() { try { Thread.sleep (200); } catch (InterruptedException e) { e.printStackTrace ( ); } flag = true; System.out.println ("flag="+flag ); } public boolean isFlag(){ return flag; } public void setFlag(boolean flag){ this.flag=flag; } }
使用synchronized后,线程每次取值都会从主存中获取,不会自己缓存一份,但是效率低,容易被阻塞
volatile:当多个线程进行操作共享数据时,可以保证内存中的数据可见.
volatile比synchronized效率高
volatile效率低在哪里?
用了之后jvm不会再重排序
1.volatile不具备互斥性,只是保证所有线程去主存中获取变量
2.不保证原子性,像i++问题这个时候需要用
利用原子变量示范:
public class TestAtomicDemo { public static void main(String[] args) { AtomicDemo ad =new AtomicDemo (); for (int i = 0; i <10 ; i++) { new Thread (ad).start (); } } } class AtomicDemo implements Runnable{ private AtomicInteger serialNumber =new AtomicInteger (0); @Override public void run() { try { Thread.sleep (200); } catch (InterruptedException e) { e.printStackTrace ( ); } System.out.println (Thread.currentThread ().getName ()+":"+getSerialNumber () ); } public int getSerialNumber(){ return serialNumber.getAndIncrement (); } }
模拟cas算法
/** * Created by yxl on 2019-07-07. */ public class TestCompareAndSwap { public static void main(String[] args) { final CompareAndSwap cas = new CompareAndSwap ( ); for (int i = 0; i < 100000; i++) { new Thread (new Runnable ( ) { @Override public void run() { int expectValue = cas.get ( ); boolean b = cas.compareAndSet (expectValue, (int) Math.random ( ) * 101); if (b==false) System.out.println (b); } }).start ( ); } } } class CompareAndSwap { private int value; public synchronized int get() { return value; } public synchronized int compareAndSwap(int expectValue, int newValue) { int oldValue = value; if (oldValue == expectValue) { this.value = newValue; } return oldValue; } public synchronized boolean compareAndSet(int expectValue, int newValue) { return expectValue == compareAndSwap (expectValue, newValue); } }
ConCurrentHashMap使用锁分段机制,相对于HashTable是直接每个方法加synchronize,效率特别低.
每次写入,都会在底层复制一个新的列表然后添加,所以这里的并发添加遍历没有报错
import java.util.Iterator; import java.util.concurrent.CopyOnWriteArrayList; /** * Created by yxl on 2019-07-07. */ public class TestCopyOnWriteArrayList { public static void main(String[] args) { HelloThread t=new HelloThread (); for (int i = 0; i < 10; i++) { new Thread (t).start (); } } } class HelloThread implements Runnable{ private static CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList ( ); static { list.add ("a"); list.add ("b"); list.add ("c"); } @Override public void run() { Iterator<String> it=list.iterator (); while(it.hasNext ()){ System.out.println (it.next () ); list.add ("AAA"); } } }
import java.util.concurrent.CountDownLatch; /** * Created by yxl on 2019-07-07. */ public class TestCountDownLatch { public static void main(String[] args) { final CountDownLatch latch=new CountDownLatch (10); LatchDemo d=new LatchDemo (latch); long start=System.currentTimeMillis (); for (int i = 0; i < 10; i++) { new Thread (d).start (); } try{ latch.await (); } catch (InterruptedException e) { e.printStackTrace ( ); } long end=System.currentTimeMillis (); System.out.println ("耗时"+(end-start) ); } } class LatchDemo implements Runnable{ private CountDownLatch latch; public LatchDemo(CountDownLatch latch){ this.latch=latch; } @Override public void run() { try { for (int i = 0; i < 50000; i++) { if (i%2 == 0){ System.out.println (i ); } } }finally { latch.countDown (); } } }
实现多线程的其中一种方式:实现Callable接口方式
import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; /** * Created by yxl on 2019-07-07. */ public class TestCallable { public static void main(String[] args) throws ExecutionException, InterruptedException { ThreadDemo td = new ThreadDemo ( ); FutureTask<Integer> result=new FutureTask<Integer> (td); new Thread (result).start (); Integer sum=result.get(); System.out.println (sum ); System.out.println ("---------" ); } } class ThreadDemo implements Callable<Integer> { @Override public Integer call() throws Exception { int sum = 0; for (int i = 0; i < 100; i++) { System.out.println (i ); sum += i; } return sum; } }