美文网首页
第一周:理解Java中的Synchronized关键字

第一周:理解Java中的Synchronized关键字

作者: 猩程变 | 来源:发表于2018-03-19 12:35 被阅读37次

    指标:理解Synchronized的含义,明确Synchronized关键字修饰普通方法、静态方法和代码块时锁对象的差异

    1、含义:Synchronized是Java中解决并发问题的一种最常见的方法,也是最简单的一种方法。用于处理多线程中访问相同资源造成冲突的一种同步锁,实现代码的中的同步机制。
    2、作用:主要有三个作用
    ①确保线程互斥的访问同步代码块
    ②保证共享变量的修改能够及时可见
    ③有效解决重排序问题
    3、修饰对象
    ①修饰普通方法,其作用范围是整个方法,作用的对象是调用这个方法的对象。

    ②修饰静态方法,其作用范围是这个静态方法,作用对象是这个类的所有对象

    ③修饰代码块,其作用范围是由{}括起来的代码块,作用的对象是调用这个代码块的对象

    一个线程访问一个对象中的synchronize同步代码块时,试图访问该对象的线程将被阻塞

    class SyncThread implements Runnable {
        private static int count;
    
        public SyncThread() {
            count = 0;
        }
    
        public void run() {
            synchronized (this) {
                for (int i = 0; i < 5; i++) {
                    try {
                        System.out.println(Thread.currentThread().getName() + ":" + (count++));
                        Thread.sleep(100);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
    
        }
    
        public int getCount() {
            return count;
        }
    }
    
    
    public class test {
        public static void main(String[] args) {
    
            SyncThread syncThread = new SyncThread();
            Thread thread1 = new Thread(syncThread, "sycn1");
            Thread thread2 = new Thread(syncThread, "sycn2");
            thread1.start();
            thread2.start();
    
        }
    
    
    }
    

    上面的代码在控制台打印时依次等待执行,结果如下

    sycn1:0
    sycn1:1
    sycn1:2
    sycn1:3
    sycn1:4
    sycn2:5
    sycn2:6
    sycn2:7
    sycn2:8
    sycn2:9
    

    当两个并发线程(thread1和thread2)访问同一个对象(syncThread)中的synchronized代码块时,在同一时刻只能有一个线程得到执行,另一个线程受阻塞,必须等待当前线程执行完这个代码块以后才能执行该代码块。Thread1和thread2是互斥的,因为在执行synchronized代码块时会锁定当前的对象,只有执行完该代码块才能释放该对象锁,下一个线程才能执行并锁定该对象

    我们把SyncThread的调用修改如下:

            Thread thread1 = new Thread(new SyncThread(), "sycn1");
            Thread thread2 = new Thread(new SyncThread(), "sycn2");
            thread1.start();
            thread2.start();
    

    执行结果如下:

    sycn1:0
    sycn2:1
    sycn1:2
    sycn2:3
    sycn2:5
    sycn1:4
    sycn2:6
    sycn1:6
    sycn1:8
    sycn2:7
    

    不是说一个线程执行synchronized代码块时其它的线程受阻塞吗?为什么上面的例子中thread1和thread2同时在执行?
    这是因为synchronized只锁定对象,每个对象只有一个锁(lock)与之相关联,而上面的代码等同于下面这段代码:

    SyncThread syncThread1 = new SyncThread();
    SyncThread syncThread2 = new SyncThread();
    Thread thread1 = new Thread(syncThread1, "SyncThread1");
    Thread thread2 = new Thread(syncThread2, "SyncThread2");
    thread1.start();
    thread2.start();
    

    这时创建了两个SyncThread的对象syncThread1和syncThread2,线程thread1执行的是syncThread1对象中的synchronized代码(run),而线程thread2执行的是syncThread2对象中的synchronized代码(run);我们知道synchronized锁定的是对象,这时会有两把锁分别锁定syncThread1对象和syncThread2对象,而这两把锁是互不干扰的,不形成互斥,所以两个线程可以同时执行

    问题答案:
    问题1:不同步,因为a1.a和a2.a不是同一个锁,锁住的是this
    问题2:同步,因为关键字static已经让这个代码块都添加上了同一把锁,锁住的是this.class

    相关文章

      网友评论

          本文标题:第一周:理解Java中的Synchronized关键字

          本文链接:https://www.haomeiwen.com/subject/zrbuqftx.html