1. 程式人生 > >Lock和synchronized使用

Lock和synchronized使用

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使用