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

 

posted @ 2016-11-24 11:23  Lammy  阅读(7091)  评论(0编辑  收藏  举报