zoukankan      html  css  js  c++  java
  • java 多线程安全--- synchronized 关键字

    1.什么线程安全问题?

    1.1 就是当多个线程共享同一个全局变量,同时对这个变量做写的时间,可能会受到其他线程的干扰,导致数据有误。


    class ThreadDemos implements Runnable {
    private int movie = 8;

    @Override
    public void run() {
    while (movie > 0) {
    try {
    Thread.sleep(10);
    } catch (Exception e) {
    // TODO: handle exception
    }
    sell();
    }
    }

    public void sell() {
    if (movie > 0) {
    System.out.println(Thread.currentThread().getName() + ",出售第" + (8 - movie + 1) + "票");
    movie--;

    }


    }
    }

    public class ThreadDemo {

    public static void main(String[] args) {
    ThreadDemos threadDemos = new ThreadDemos();
    Thread t1 = new Thread(threadDemos, "美团买票");
    Thread t2 = new Thread(threadDemos, "门店买票");
    t1.start();
    t2.start();
    }

    }

    运行结果:

     由此我们可以发现2个窗口会出现同一张票,就出现了线程安全问题,如果2个不同的人买了同一张票,这个时间检票员是该让哪个人进去看电影那?

    2.怎么样解决线程安全问题?

    2.1 使用synchronized 同步代码块  代码如下:


    class ThreadDemos implements Runnable {
    private int movie = 8;
    private Object object = new Object();

    @Override
    public void run() {
    while (movie > 0) {
    try {
    Thread.sleep(10);
    } catch (Exception e) {
    // TODO: handle exception
    }
    sell();
    }
    }

    public void sell() {
    synchronized (object) {
    if (movie > 0) {
    System.out.println(Thread.currentThread().getName() + ",出售第" + (8 - movie + 1) + "票");
    movie--;

    }
    }


    }
    }

    public class ThreadDemo {

    public static void main(String[] args) {
    ThreadDemos threadDemos = new ThreadDemos();
    Thread t1 = new Thread(threadDemos, "美团买票");
    Thread t2 = new Thread(threadDemos, "门店买票");
    t1.start();
    t2.start();
    }

    }
    代码运行结果:

    使用 synchronized 同步代码块 就不会出现2个窗口会出现同一张票的安全性问题

    使用synchronized 的  条件:1.必须要有2个线程以上的,需要同步  2.多个线程想要同步,必须要使用同一把锁 3.保证只有一个线程运行执行

    使用synchronized 同步代码块 的原理:有一个线程已经拿到锁了,其他线程已经有cpu执行的,那么这个线程会等待拿到锁的那个线程执行完毕释放锁

    使用synchronized 的缺点:效率低,因为线程会抢锁

    2.2使用 同步函数解决线程安全:


    class ThreadDemos implements Runnable {
    private int movie = 8;

    @Override
    public void run() {
    while (movie > 0) {
    try {
    Thread.sleep(10);
    } catch (Exception e) {
    // TODO: handle exception
    }
    sell();
    }
    }

    public synchronized void sell() {
    if (movie > 0) {
    System.out.println(Thread.currentThread().getName() + ",出售第" + (8 - movie + 1) + "票");
    movie--;

    }


    }
    }

    public class ThreadDemo05 {

    public static void main(String[] args) {
    ThreadDemos threadDemos = new ThreadDemos();
    Thread t1 = new Thread(threadDemos, "美团买票");
    Thread t2 = new Thread(threadDemos, "门店买票");
    t1.start();
    t2.start();
    }

    }
    代码运行结果:

     使用同步函数 在需要同步的方法上面加上  synchronized 关键字,同步函数使用的是 this 锁

    2.3使用静态同步函数

    class ThreadDemos implements Runnable {
    private static int movie = 8;

    @Override
    public void run() {
    while (movie > 0) {
    try {
    Thread.sleep(10);
    } catch (Exception e) {
    // TODO: handle exception
    }
    sell();
    }
    }

    public static synchronized void sell() {

    if (movie > 0) {
    System.out.println(Thread.currentThread().getName() + ",出售第" + (8 - movie + 1) + "票");
    movie--;

    }


    }
    }

    public class ThreadDemo05 {

    public static void main(String[] args) {
    ThreadDemos threadDemos = new ThreadDemos();
    Thread t1 = new Thread(threadDemos, "美团买票");
    Thread t2 = new Thread(threadDemos, "门店买票");
    t1.start();
    t2.start();
    }

    }
    运行结果:

    静态同步函数使用的是 当前字节码文件

  • 相关阅读:
    计算机基础总结
    Apache安装错误 APR not found解决方法
    一、编译错误
    2.2 进程控制之进程共享
    2.1 进程控制之fork创建子进程
    ARM串口控制终端命令
    u-boot、kernel、root系统烧写和挂载命令命令
    8.1 编写USB鼠标驱动程序,并测试
    八、USB驱动分析
    Source Insight的使用
  • 原文地址:https://www.cnblogs.com/cwj1102/p/13354381.html
Copyright © 2011-2022 走看看