• 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
  • 相关阅读:
    Mysql8 连接提示 Client does not support authentication protocol requested by server; consider upgrading MySQL client 解决方法
    CMSampleBufferRef解析
    AVCaptureInput和AVCaptureOutput子类介绍
    六大设计原则
    UIView绘制原理,异步绘制
    使用Pods中使用Swift和Objective-C混编-编译不通过的原因
    SVN版本控制说明与相关指令
    KVO
    KVC
    Java从0到1的成长之路
  • 原文地址:https://www.cnblogs.com/bokeofzp/p/6097032.html
Copyright © 2020-2023  润新知