排他鎖和共享鎖:
讀寫鎖:既是排他鎖,又是共享鎖。讀鎖,共享鎖,寫鎖:排他鎖
讀和讀是不互斥的
import java.util.HashMap; import java.util.Map; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; public class Demo { private Map<String, Object> map=new HashMap<>(); private ReadWriteLock rwl=new ReentrantReadWriteLock(); private Lock r=rwl.readLock(); private Lock w=rwl.writeLock(); public Object get(String key){ r.lock(); System.out.println(Thread.currentThread().getName()+"讀操作正在執行。。。"); try { try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } return map.get(key); } finally{ r.unlock(); System.out.println(Thread.currentThread().getId()+"讀操作執行完畢。。。"); } } public void put(String key,Object value){ w.lock(); System.out.println(Thread.currentThread().getName()+"寫操作在執行。。。"); try { try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } map.put(key, value); } finally { w.unlock(); System.out.println(Thread.currentThread().getName()+"寫操作執行完畢。。。"); } } }
public class Main { public static void main(String[] args) { Demo d=new Demo(); d.put("key1", "value1"); // new Thread(new Runnable() { // @Override // public void run() { // d.put("key1", "value1"); // } // }).start(); new Thread(new Runnable() { @Override public void run() { System.out.println(d.get("key1")); } }).start(); new Thread(new Runnable() { @Override public void run() { System.out.println(d.get("key1")); } }).start(); new Thread(new Runnable() { @Override public void run() { System.out.println(d.get("key1")); } }).start(); // new Thread(new Runnable() { // @Override // public void run() { // d.put("key3", "value3"); // } // }).start(); } }
讀寫鎖需要保存的狀態:
寫鎖重入的次數
讀鎖的個數
每個讀鎖重入的次數
鎖降級:是指寫鎖降為讀鎖
在寫鎖沒有釋放的時候,獲取到讀鎖,在釋放寫鎖
鎖升級:
把讀鎖,升級為寫鎖
在讀鎖沒有釋放的時候,獲取到寫鎖,在釋放讀鎖
private volatile boolean isUpdate; public void readWrite(){ r.lock(); if(isUpdate){ r.unlock(); w.lock(); map.put("XXX", "xxx"); r.lock(); w.unlock(); } Object obj=map.get("XXX"); System.out.println(obj); r.unlock(); }
出現線程安全性問題的條件
1.必須在多線程的環境下
2.必須有共享資源
3.對共享資源進行非原子性操作
解決線程安全性問題的途徑
1.synchronized 相對慢(偏向鎖、輕量級鎖、重量級鎖)
2.volatile(只能保證讀寫操作,不能保證非原子性操作)
3.JDK提供的原子類
4.使用Lock(共享鎖、排它鎖)
認識的“*鎖“
1.偏向鎖
2.輕量級鎖
3.重量級鎖
4.重入鎖
5.自旋鎖
6.共享鎖
7.獨占鎖
8.排它鎖
9.讀寫鎖
10.公平鎖
11.非公平鎖
12.死鎖
13.活鎖
public class Tmall { public int count; public final int MAX_COUNT=10; public synchronized void push(){ while(count>=MAX_COUNT) try { System.out.println(Thread.currentThread().getName()+ "庫存數量達到上限,生產者停止生產。"); wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } count++; System.out.println(Thread.currentThread().getName() +"生產者生產,當前庫存為:"+count); notify(); } public synchronized void task(){ while(count<=0) try { System.out.println(Thread.currentThread().getName()+ "庫存數量為零,消費着等待。"); wait(); } catch (InterruptedException e) { e.printStackTrace(); } count--; System.out.println(Thread.currentThread().getName()+ "消費者消費,當前庫存為:"+count); notify(); } }
public class TaskTarget implements Runnable { private Tmall tmall; public TaskTarget(Tmall tmall) { this.tmall=tmall; } @Override public void run() { tmall.task(); } }
public class PushTarget implements Runnable{ private Tmall tmall; public PushTarget(Tmall tmall) { this.tmall=tmall; } @Override public void run() { while(true){ tmall.push(); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } }
public class Main { public static void main(String[] args){ Tmall tmall=new Tmall(); PushTarget p=new PushTarget(tmall); TaskTarget t=new TaskTarget(tmall); new Thread(p).start(); new Thread(p).start(); new Thread(p).start(); new Thread(t).start(); new Thread(t).start(); new Thread(t).start(); } }
Condition的使用。
public class Demo5 { private int signal; //執行順序 a->b->c public synchronized void a(){ while(signal!=0){ try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("a"); signal++; notifyAll(); } public synchronized void b(){ while(signal!=1){ try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("b"); signal++; notifyAll(); } public synchronized void c(){ while(signal!=2){ try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("c"); signal=0; notifyAll(); } public static void main(String[] args){ Demo5 d=new Demo5(); A a=new A(d); B b=new B(d); C c=new C(d); new Thread(a).start(); new Thread(b).start(); new Thread(c).start(); } } class A implements Runnable{ private Demo5 demo; public A(Demo5 demo){ this.demo=demo; } @Override public void run(){ while(true){ demo.a(); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } } class B implements Runnable{ private Demo5 demo; public B(Demo5 demo){ this.demo=demo; } @Override public void run(){ while(true){ demo.b(); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } } class C implements Runnable{ private Demo5 demo; public C(Demo5 demo){ this.demo=demo; } @Override public void run(){ while(true){ demo.c(); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } }
用condition
import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class Demo { private int signal; Lock lock = new ReentrantLock(); Condition a = lock.newCondition(); Condition b = lock.newCondition(); Condition c = lock.newCondition(); public void a() { lock.lock(); while(signal != 0 ) { try { a.await(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("a"); signal ++; b.signal(); lock.unlock(); } public void b() { lock.lock(); while(signal != 1) { try { b.await(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } System.out.println("b"); signal ++; c.signal(); lock.unlock(); } public void c () { lock.lock(); while(signal != 2) { try { c.await(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("c"); signal = 0; a.signal(); lock.unlock(); } public static void main(String[] args) { Demo d = new Demo(); A a = new A(d); B b = new B(d); C c = new C(d); new Thread(a).start(); new Thread(b).start(); new Thread(c).start(); } } class A implements Runnable { private Demo demo; public A(Demo demo) { this.demo = demo; } @Override public void run() { while(true) { demo.a(); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } } class B implements Runnable { private Demo demo; public B(Demo demo) { this.demo = demo; } @Override public void run() { while(true) { demo.b(); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } } class C implements Runnable { private Demo demo; public C(Demo demo) { this.demo = demo; } @Override public void run() { while(true) { demo.c(); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } }
實現一個隊列:
import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class MyQueue<E> { private Object[] obj; private int addIndex; private int removeIndex; private int queueSize; private Lock lock=new ReentrantLock(); Condition addCondition=lock.newCondition(); Condition removeCondition=lock.newCondition(); public MyQueue(int count){ obj=new Object[count]; } public void add(E e){ lock.lock(); //滿了之后等待 while(queueSize==obj.length){ try { addCondition.await(); } catch (InterruptedException e1) { e1.printStackTrace(); } } obj[addIndex]=e; if(++addIndex==obj.length){ //先比較在++ addIndex=0; } queueSize++; removeCondition.signal(); lock.unlock(); } public void remove(){ lock.lock(); while (queueSize==0) { try { removeCondition.await(); } catch (InterruptedException e) { e.printStackTrace(); } } obj[removeIndex]=null; if(++removeIndex==obj.length){ removeIndex=0; } queueSize--; addCondition.signal(); lock.unlock(); } }