zoukankan      html  css  js  c++  java
  • synchronized的对象锁和类锁

    概念

    synchronized 是 Java 中的关键字,是利用锁的机制来实现同步的。

    锁机制有如下两种特性:

    • 互斥性:即在同一时间只允许一个线程持有某个对象锁,通过这种特性来实现多线程中的协调机制,这样在同一时间只有一个线程对需同步的代码块(复合操作)进行访问。互斥性我们也往往称为操作的原子性。

    • 可见性:必须确保在锁被释放之前,对共享变量所做的修改,对于随后获得该锁的另一个线程是可见的(即在获得锁时应获得最新共享变量的值),否则另一个线程可能是在本地缓存的某个副本上继续操作从而引起不一致。

    对象锁

    synchronized修饰非静态方法时是对象锁,等同于synchronized(this),在同一个对象中是线程安全的。

    package com.dwz.concurrency.chapter7;
    /**
     *     两个方法锁定的都是this即同一个对象thisLock,
     *     同时调用的结果是一个执行完再执行下一个
     */
    public class SynchronizedThis {
        public static void main(String[] args) {
            ThisLock thisLock = new ThisLock();
            new Thread("T1") {
                @Override
                public void run() {
                    thisLock.m1();
                }
            }.start();
            
            new Thread("T2") {
                @Override
                public void run() {
                    thisLock.m2();
                }
            }.start();
        }
    }
    
    class ThisLock {
      public synchronized void m1() { try { System.out.println(Thread.currentThread()); Thread.sleep(10_000); } catch (InterruptedException e) { e.printStackTrace(); } } public synchronized void m2() { try { System.out.println(Thread.currentThread()); Thread.sleep(10_000); } catch (InterruptedException e) { e.printStackTrace(); } } }

     执行结果:m1和m2先后执行

    package com.dwz.concurrency.chapter7;
    /**
     *     锁定的是两个不同的对象,没有起到锁的作用,还是多线程执行
     */
    public class SynchronizedThis2 {
        public static void main(String[] args) {
            ThisLock2 thisLock = new ThisLock2();
            new Thread("T1") {
                @Override
                public void run() {
                    thisLock.m1();
                }
            }.start();
            
            new Thread("T2") {
                @Override
                public void run() {
                    thisLock.m2();
                }
            }.start();
        }
    }
    
    class ThisLock2 {
        private final Object LOCK = new Object();
        
        public void m2() {
            synchronized (LOCK) {
                try {
                    System.out.println(Thread.currentThread());
                    Thread.sleep(10_000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
        
        public void m1() {
            synchronized (this) {
                try {
                    System.out.println(Thread.currentThread());
                    Thread.sleep(10_000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    执行结果:m1和m2同时执行

    类锁

    synchronized修饰静态方法时是类锁,等同于synchronized(类.class),是线程安全的。

    package com.dwz.concurrency.chapter7;
    
    public class SynchronizedStatic {
        public synchronized static void m1() {
            System.out.println("m1" + Thread.currentThread());
            try {
                Thread.sleep(10_000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        
        public synchronized static void m2() {
            System.out.println("m2" + Thread.currentThread());
            try {
                Thread.sleep(10_000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        
        public synchronized static void m3() {
            System.out.println("m3" + Thread.currentThread());
            try {
                Thread.sleep(10_000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    测试类

    package com.dwz.concurrency.chapter7;
    
    public class SynchronizedTest2 {
        public static void main(String[] args) {
            new Thread("T1") {
                @Override
                public void run() {
                    SynchronizedStatic.m1();
                };
            }.start();
            
            new Thread("T2") {
                @Override
                public void run() {
                    SynchronizedStatic.m2();
                };
            }.start();
            
            new Thread("T3") {
                @Override
                public void run() {
                    SynchronizedStatic.m3();
                };
            }.start();
        }
    }

    执行结果:T1 T2 T3是先后执行的

    总结

    1、对于静态方法,由于此时对象还未生成,所以只能采用类锁;

    2、只要采用类锁,就会拦截所有线程,只能让一个线程访问。

    3、对于对象锁(this),如果是同一个实例,就会按顺序访问,但是如果是不同实例,就可以同时访问。

    4、如果对象锁跟访问的对象没有关系,那么就会都同时访问。

  • 相关阅读:
    CSS中float与A标签的疑问
    常用的Css命名方式
    div css 盒子模型
    HTML初级教程 表单form
    Redis学习记录(二)
    Redis学习记录(一)
    Java源码——HashMap的源码分析及原理学习记录
    java编程基础——从上往下打印二叉树
    java编程基础——栈压入和弹出序列
    java基础编程——获取栈中的最小元素
  • 原文地址:https://www.cnblogs.com/zheaven/p/12058497.html
Copyright © 2011-2022 走看看