Lock和synchronized使用
阿新 • • 發佈:2017-12-28
bject adl 每次 .get shm runnable start new while
該文章主要講解如何快速應用Lock和synchronized
讀者可以自行學習Lock和synchronized系統級比較;可參考並發實戰等,自己決定什麽場景下使有哪種鎖
Lock使用案例:
public class Person {
//兩個線程同時調用這個方法 public void say(String msg){ int len = msg.length(); for(int i=0;i<len;i++){ System.out.print(msg.charAt(i)); } System.out.println(); } }
public class LockTest { public static void main(String[] args) { Person person = new Person(); new Thread(new Runnable(){ @Override public void run() { while(true){ try { Thread.sleep(20); }catch (InterruptedException e) { e.printStackTrace(); } person.say("haohaoxuexi"); } } }).start(); new Thread(new Runnable(){ @Override public void run() {while(true){ try { Thread.sleep(20); } catch (InterruptedException e) { e.printStackTrace(); } person.say("tiantianxiangshang"); } } }).start(); } }
輸出的結果:
haohaoxuexi
tianhaohaoxuexitianxiangshang
hatiantianxiangshangoha
oxuexi
htiantianxiangshangaohaoxuexi
以上結果是隨機生成的,每次的結果可能都不一樣;主要證明並發一個對象方法時候存在線程安全問題
修改方法:
public class Person {
//為對象創建一把鎖 Lock lock = new ReentrantLock(); public void say(String msg){ int len = msg.length();
//加鎖 lock.lock(); try{ for(int i=0;i<len;i++){ System.out.print(msg.charAt(i)); } System.out.println(); }finally{
//解鎖 lock.unlock(); } } }
此時是結果正常:
tiantianxiangshang
haohaoxuexi
tiantianxiangshang
haohaoxuexi
tiantianxiangshang
haohaoxuexi
tiantianxiangshang
haohaoxuexi
基於Lock讀寫鎖的案例:
public class Cache { //創建一個緩存 private static Map<String, Object> cache = new HashMap<String, Object>(); //創建讀寫鎖 private static ReadWriteLock rwl = new ReentrantReadWriteLock(); public static Object getData(String key){ //加讀鎖 rwl.readLock().lock(); Object value = null; try{ value = cache.get(key); if(value == null){ //釋放讀鎖 rwl.readLock().unlock(); //加寫鎖 rwl.writeLock().lock(); try{ if(value==null){ value = "查詢介質獲取數據"; cache.put(key, value); } }finally{ //加讀鎖 rwl.readLock().lock(); //釋放寫鎖 rwl.writeLock().unlock(); } } }finally{ //釋放讀鎖 rwl.readLock().unlock(); } return value; } }
synchronized使用案例
public class Person { //兩個線程同時調用這個方法 public void say(String msg){ int len = msg.length(); for(int i=0;i<len;i++){ System.out.print(msg.charAt(i)); } System.out.println(); } } 把上述代碼修改成以下即可 public class Person { public synchronized void say(String msg){ int len = msg.length(); for(int i=0;i<len;i++){ System.out.print(msg.charAt(i)); } System.out.println(); } } 或者修改成以下代碼 public class Person { public void say(String msg){ int len = msg.length(); synchronized(Person.class){ for(int i=0;i<len;i++){ System.out.print(msg.charAt(i)); } System.out.println(); } } }
Lock和synchronized使用