• Java多线程同步_synchronized


    1.synchronized是什么?
    synchronized是Java中的关键字,是一种同步锁。它修饰的对象有以下几种:
    1. 修饰一个代码块,被修饰的代码块称为同步语句块,其作用的范围是大括号{}括起来的代码,作用的对象是调用这个代码块的对象(锁对象);
    2. 修饰一个(静态)方法,被修饰的方法称为同步(静态)方法,其作用的范围是整个方法,作用的对象是调用这个方法的对象;
    3. 修饰一个类,其作用的范围是synchronized后面括号括起来的部分,作用主的对象是这个类的所有对象。
    2.synchronized有什么用?
    请看下面这一段代码:

    public class TicketDemo {
        public static void main(String[] args) {
            Ticket ticket1 = new Ticket();
            Ticket ticket2 = new Ticket();
            ticket1.setName("窗口1");
            ticket2.setName("窗口2");
            ticket1.start();
            ticket2.start();
        }
    }
    
    class Ticket extends Thread {
        public static int count = 100; // 共有100张票
    
        @Override
        public void run() {
            while (count > 0) 
                System.out.println(Thread.currentThread().getName() + "取到了第" + (count--));
        try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }    
             }
        }
    }

    这是模拟的窗口卖票,其中有两个窗口,当这两个窗口访问同一个变量count时,运行结果出现了重复的值,请看下图:

    这是因为窗口2取到了第86张票还没执行完毕(即打印出本次循环的结果并执行--操作),窗口二这个子线程加入了进来,取到了count的值,这样导致了窗口1和窗口2取到了相同的值,这就是没有同步的结果,简单的说,就是多个线程访问同一个临界资源时所造成的,解决方案就是给这个临界资源加上一把锁(使用synchronized时一种方法),使得一个线程还没访问结束之前,其他线程不得访问这个临界资源。
    3.synchronized的使用

    下面就使用synchronized关键词来解决这个问题。
    (1)synchronized修饰类:将这个类放到synchronized的大括号里面;
    (2)synchronized修饰方法:直接在方法名前面加上synchronized就OK了。
    (3)synchronized修饰一段代码块,这里推荐使用这种,前两种不推荐使用。
    请看下面一段代码:

    public class TicketDemo {
        public static void main(String[] args) {
            Ticket ticket1 = new Ticket();
            Ticket ticket2 = new Ticket();
            ticket1.setName("窗口1");
            ticket2.setName("窗口2");
            ticket1.start();
            ticket2.start();
        }
    }
    
    class Ticket extends Thread {
        public static int count = 100; // 共有100张票
    
        @Override
        public void run() {
            synchronized (this) {
                while (count > 0) {
                    System.out.println(Thread.currentThread().getName() + "取到了第" + (count--));
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    这就是synchronized修饰的一段代码块,这种方法要注意的点是必须要把使用了临界资源的代码块放进synchronized大括号里,小括号里面的是锁对象,一定要注意的一点是,锁住的必须是同一个对象。

    在实际开发中,一般采用第三种方法,而不建议前两种,这样可以提升效率。

     

  • 相关阅读:
    SQL 操作结果集 -并集、差集、交集、结果集排序
    bootstrap的css和js
    pandas DataFrame数据转为list
    nodejs 不同请求获取前端传的参数
    微信小程序switch组件尺寸控制
    vue-cli项目部署到服务器
    element-ui table 底部滚动条问题
    简单配色
    浏览器滚动条自定义化
    element table固定表头,表的高度自适应解决方法
  • 原文地址:https://www.cnblogs.com/ericz2j/p/10282313.html
Copyright © 2020-2023  润新知