Java 的2種鎖用法


1、synchronized

同步鎖的用法。它可以在代碼中使用,也可以用來修飾函數。它的特性是:同一時間內,只有一個擁有鎖的線程才能運行。

synchronized (obj) {
          while (<condition does not hold>)
                 obj.wait();
           ... // Perform action appropriate to condition
       }

常用方法:

obj為鎖對象

obj.wait() :調用后,該線程會釋放同步鎖obj對象,並使進程處於等待狀態。

obj.notify():調用后將喚醒等待obj鎖對象的線程隊列中的第一個線程。喚醒等待該鎖的線程隊列中的第一個線程,並且當前進程釋未釋放鎖,得在當前線程中需調用wait釋放鎖,使當前進程等待,喚醒的線程才可以執行,否則就等待線程釋放它等待的鎖。

obj.notifyAll() :調用后喚醒等待obj對象的線程隊列中的所有線程,誰得到了線程釋放的鎖誰就運行。

NOTE:notify 和notifyAll只是激活了線程,但線程還是得等到鎖對象才能運行。若不激活wait()后線程阻塞了,它不會主動去獲取鎖,因此當沒有線程占用鎖時,若沒激活線程仍然不會運行。

例如下面的例子,大於105的時候賣票,低於100的時候制票:

public class LockDemo {
    
    private static int ticketNumber = 103;
    private static final Object ticketLock = new Object();
    public static void main(String[] args) throws InterruptedException {
        
        Thread t1 = new Thread(new SellTicket());
        t1.start();
        Thread t2 = new Thread(new MakeTicket());
        t2.start();
    
//        synchronized (ticketLock) {        
//            while(true)
//            {
//                ticketLock.wait();
//                System.out.println("dddddddddddddddddddddd");
//            }
//            
//        }
        
    }
    
    static class SellTicket implements Runnable{

        public void run()  {

            synchronized (ticketLock)
            {    
            while(true){
            
                if(ticketNumber <= 100)
                    {                                            
                        //少於100張票后就停止售票,制造票,這里wait()會是釋放ticketLock鎖對象,讓制票線程啟動
                            System.out.println("賣完票");
                            ticketLock.notify();
                            try {
                                ticketLock.wait();
                            } catch (InterruptedException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            }
                        
                    }
                    else
                        {
                        try
                        {
                            Thread.sleep(1000);
                        }
                        catch(Exception e)
                        {
                            
                        }
                        System.out.println("賣票"+ ticketNumber);
                            ticketNumber--;
                        }
            }
        }
        }
    }

static    class MakeTicket implements Runnable{

        public void run() {
            
            synchronized (ticketLock)
            {
                while(true)
                {                
                    if(ticketNumber>=105)
                    {                
                        System.out.println("制造好票");
                            ticketLock.notify();
                            try {
                                ticketLock.wait();
                            } catch (InterruptedException e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                            }
                        
                    }
                    else
                    {
                        try
                        {
                            Thread.sleep(1000);
                        }
                        catch(Exception e)
                        {
                            
                        }
                        System.out.println("制造票" + ticketNumber);
                        ticketNumber++;
                    }
                }
            }
        }
    }

}
View Code

2、異步鎖 Lock

jdk1.5提供了多線程的升級解決方法(顯示的鎖機制) 將同步synchronized替換成了顯示的Lock操作

----》lock() unlock() 將Object中的wait、notify/notifyAll 替換成了 Condition (await/signal/signalAll)

該對象可以 Lock.newCondition() 獲取 一個鎖可以綁定多個condition對象,避免了因同步嵌套導致死鎖問題的發生,激活指定的線程。

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;


public class LockDemo2 {
    
    private static int ticketNumber = 103;
    private static final Object ticketLock = new Object();
    private static Lock lock  = new ReentrantLock();
    private static Condition condition_sell = lock.newCondition();
    private static Condition condition_make = lock.newCondition();
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Thread t1 = new Thread(new SellTicket());
        t1.start();
        Thread t2 = new Thread(new MakeTicket());
        t2.start();
        
    }
    
    static class SellTicket implements Runnable{

        public void run()  {
            // TODO Auto-generated method stub
            lock.lock();
            try{
            while(true){    
                if(ticketNumber <= 100)
                    {                                            
                        //少於100張票后就停止售票,制造票,這里wait()會是釋放ticketLock鎖對象,讓制票線程啟動                
                        condition_make.signal();//激活制票的線程
                        condition_sell.await();                                
                    }
                    else
                        {
                            Thread.sleep(1000);                            
                            System.out.println("賣票"+ ticketNumber);
                                ticketNumber--;        
                        }            
                }
            }
            catch(Exception e){}
            finally
            {
                lock.unlock();
            }
        }
    }

static    class MakeTicket implements Runnable{

        public void run() {
            // TODO Auto-generated method stub                        
            lock.lock();
            try{
                while(true)        
                {                    
                    if(ticketNumber>=105)
                    {
                        condition_sell.signal();//激活賣票的線程
                        condition_make.await();                                            
                    }
                    else
                    {                    
                        Thread.sleep(1000);                                            
                        System.out.println("制造票" + ticketNumber);
                        ticketNumber++;
                    }                
                }
            }catch(Exception e){}
                finally
                {
                    lock.unlock();
                }            
        }
        
}
    

}
View Code

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM