2020-03-23 · 线程同步之Lock(),以及练习题

一、Lock()锁

1.1 Lock()的基本介绍:
  • 从JDK 5.0开始,Java就提供了更加强大的线程同步机制 — — 通过显示定义同步锁对象来实现同步。
  • java.util.concurrent.locks.Lock接口是控制多个线程对共享资源进行访问的工具。
  • ReentrantLock 类实现了 Lock ,它拥有与synchronized 相同的并发性和内存语义,在实现线程安全的控制中,比较常用的是ReentrantLock,可以显式加锁、释放锁。
1.2 公式图:
Lock(锁)公式
1.3 代码演示:
package com.atguigu.exer;

import java.util.concurrent.locks.ReentrantLock;

/**
 *  解决线程安全问题的方式三:Lock锁 --- JDK5.0新增
 * 
 * 1.面试题:synchronized 与 Lock 的异同?
 *      相同:都是解决线程的安全问题。
 *      不同:synchronized机制在执行完相应的同步代码以后,自动释放同步监视器。
 *           lock需要手动启动同步(lock()方法),同时结束同步也需要手动释放同步监视器(unlock()方法)。
 *           
 * 2.优先使用顺序:
 * Lock  同步代码块(已经进入了方法体,分配了相应资源)  同步方法
 * (在方法体之外)
 * 
 * 3.面试题:如何解决线程安全问题?有几种方式
 * 
 * @author czh
 * @create 2020-03-23-22:02
 */

class WTest implements Runnable{

    private int ticket = 100;

    //1.实例化ReentrantLock
    private ReentrantLock lock = new ReentrantLock(true);

    @Override
    public void run() {
        while (true){

            try {//2.1

                //2.2调用锁定方法:lock()
                lock.lock();

                if (ticket > 0) {

                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    System.out.println(Thread.currentThread().getName() + "卖票:票号为:" + ticket);
                    ticket--;
                } else {
                    break;
                }
            } finally {
                //3.调用解锁的方法:unlock()
                lock.unlock();
            }


        }
    }
}

public class Test {
    public static void main(String[] args) {
        WTest wTest = new WTest();

        Thread t1 = new Thread(wTest);
        Thread t2 = new Thread(wTest);
        Thread t3 = new Thread(wTest);

        t1.setName("窗口1");
        t2.setName("窗口2");
        t3.setName("窗口3");

        t1.start();
        t2.start();
        t3.start();
    }
}



二、线程同步的练习题 ①

2.1 代码演示:
package com.atguigu.exer;

/**
 * 银行有一个账户。
 * 有两个储户分别向同一个账户存3000元,
 * 每次存1000,存3次。每次存完打印账户余额。
 *
 * 分析:
 * 1.是否是多线程问题? 是,一个账户,两个储户使用。
 * 2.是否有共享数据? 有,储户的余额。
 * 3.是否有线程安全问题? 有。
 * 4.考虑如何解决线程安全问题? 同步机制(三种方法)。
 *
 * @author czh
 * @create 2020-03-23-22:02
 */
class Accountt{//创建银行账户
    private double balance;

    //构造器快捷键:alt + insert
    public Accountt(double balance) {
        this.balance = balance;
    }

    //存钱
    //这里用继承来同步,默认使用了this
    //但是该方法在account下,所以还是安全的
    public synchronized void depositt(double amt){

        if (amt>0) {
            balance += amt;

            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println(Thread.currentThread().getName() + "存钱成功。余额为:" + balance);
        }

    }
}


class Customerr extends Thread{//储户

    private Accountt acctt;

    //alt + insert
    public Customerr(Accountt acctt) {
        this.acctt = acctt;
    }

    @Override
    public void run() {
        for (int i = 0; i < 3; i++) {
            acctt.depositt(1000);
        }
    }
}


public class Test {
    public static void main(String[] args) {
        Accountt accountt = new Accountt(0);

        Customerr t1 = new Customerr(accountt);
        Customerr t2 = new Customerr(accountt);

        t1.setName("甲");
        t2.setName("乙");

        t1.start();
        t2.start();
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容