• java多线程 -- 同步鎖


    为了解决多线程安全问题
    在 Java 5.0 之前,协调共享对象的访问时可以使用的机制只有 synchronized 和 volatile 。
    Java 5.0 后增加了一些新的机制,但并不是一种替代内置锁的方法,而是当内置锁不适用时,作为一种可选择的高级功能。

    隐式锁

    synchronized

    1. 同步代码块;
    2. 同步方法。

    显示锁 Lock

    jdk 1.5 后:同步锁 Lock 需要通过 lock() 方法上锁,必须通过 unlock() 方法进行释放锁。
    ReentrantLock 实现了 Lock 接口,并提供了与synchronized 相同的互斥性和内存可见性。但相较于synchronized 提供了更高的处理锁的灵活性。

    Lock使用方式:

    Lock lock = new ReentrantLock();
    lock.lock();
    try {
    } finally {
    lock.unlock();
    }

    相关API:

    1. void lock() 获取锁。
    2. void lockInterruptibly() 如果当前线程未被中断,则获取锁。
    3. Condition newCondition() 返回绑定到此 Lock 实例的新 Condition 实例。
    4. boolean tryLock() 仅在调用时锁为空闲状态才获取该锁。
    5. boolean tryLock(long time, TimeUnit unit) 如果锁在给定的等待时间内空闲,并且当前线程未被中断,则获取锁。
    6. void unlock()释放锁。

    不使用锁出现多线程安全问题demo:

    package com.company;
    
    public class TestLock {
    
        public static void main(String[] args) {
            Ticket ticket = new Ticket();
    
            new Thread(ticket, "1号窗口").start();
            new Thread(ticket, "2号窗口").start();
            new Thread(ticket, "3号窗口").start();
        }
    
    }
    
    class Ticket implements Runnable{
    
        private int tick = 100;
    
    
        @Override
        public void run() {
            while(true){
                if(tick > 0){
                    try {
                        Thread.sleep(200);
                    } catch (InterruptedException e) {
                    }
    
                    System.out.println(Thread.currentThread().getName() + " 完成售票,余票为:" + --tick);
                }
    
            }
        }
    
    }

    看出现的问题(截取结果中一部分):

    3号窗口 完成售票,余票为:10
    1号窗口 完成售票,余票为:8
    2号窗口 完成售票,余票为:8
    3号窗口 完成售票,余票为:8
    2号窗口 完成售票,余票为:7
    1号窗口 完成售票,余票为:7
    3号窗口 完成售票,余票为:7
    1号窗口 完成售票,余票为:6
    2号窗口 完成售票,余票为:5
    3号窗口 完成售票,余票为:4
    3号窗口 完成售票,余票为:3
    1号窗口 完成售票,余票为:3
    2号窗口 完成售票,余票为:3
    3号窗口 完成售票,余票为:2
    1号窗口 完成售票,余票为:0
    2号窗口 完成售票,余票为:1

    现在我们用Lock来进行处理:

    package com.company;
    
    import java.util.concurrent.locks.Lock;
    import java.util.concurrent.locks.ReentrantLock;
    
    public class TestLock {
    
        public static void main(String[] args) {
            Ticket ticket = new Ticket();
    
            new Thread(ticket, "1号窗口").start();
            new Thread(ticket, "2号窗口").start();
            new Thread(ticket, "3号窗口").start();
        }
    
    }
    
    class Ticket implements Runnable {
    
        private int tick = 100;
        private Lock lock = new ReentrantLock();
    
        @Override
        public void run() {
            while (true) {
                try {
                    lock.lock();
                    if (tick > 0) {
                        try {
                            Thread.sleep(200);
                        } catch (InterruptedException e) {
                        }
    
                        System.out.println(Thread.currentThread().getName() + " 完成售票,余票为:" + --tick);
                    }
                } finally {
                    lock.unlock();
                }
    
    
            }
        }
    
    }

    看下结果(当然也是一部分),很完美解决多线程安全问题:

    2号窗口 完成售票,余票为:20
    2号窗口 完成售票,余票为:19
    2号窗口 完成售票,余票为:18
    2号窗口 完成售票,余票为:17
    2号窗口 完成售票,余票为:16
    2号窗口 完成售票,余票为:15
    2号窗口 完成售票,余票为:14
    2号窗口 完成售票,余票为:13
    2号窗口 完成售票,余票为:12
    2号窗口 完成售票,余票为:11
    2号窗口 完成售票,余票为:10
    2号窗口 完成售票,余票为:9
    2号窗口 完成售票,余票为:8
    2号窗口 完成售票,余票为:7
    2号窗口 完成售票,余票为:6
    2号窗口 完成售票,余票为:5
    2号窗口 完成售票,余票为:4
    2号窗口 完成售票,余票为:3
    2号窗口 完成售票,余票为:2
    2号窗口 完成售票,余票为:1
    2号窗口 完成售票,余票为:0
  • 相关阅读:
    上传文件
    Win10中英文的切换
    2015 4.15笔试
    wpf的学习日志(二)
    静态类
    面试宝典
    设计模式 --- 模型-视图-控制器(Model View Controller)
    设计模式 --- 单例模式(Singleton)
    iOS 应用架构浅谈
    (转)Block的使用
  • 原文地址:https://www.cnblogs.com/androidsuperman/p/6649267.html
Copyright © 2020-2023  润新知