美文网首页Java 杂谈java多线程
Java 多线程(三):Synchronized 详解

Java 多线程(三):Synchronized 详解

作者: 聪明的奇瑞 | 来源:发表于2018-07-03 17:28 被阅读34次

    案例需要自己运行一遍代码看输出结果才能理解得更深刻

    Synchronized 方法锁与代码锁

    • synchronized 修饰方法时为方法锁,只有获得当前实例对象的锁的线程才能执行对象加锁的方法
    // (1)修饰普通方法-对象锁
    public synchronized void a() {}
    // (2)修饰静态方法-类锁
    public static synchronized void a() {}
    
    • synchronized 还可以修饰代码块,只有获得指定对象(syncObject)锁的线程才可以执行锁内的代码
    // (1)修饰代码块-对象锁
    public void a() {
        synchronized(syncObject){
            
        }
    }
    // (2)修饰代码块-类锁
    public void a() {
        synchronized(XXX.class){
            
        }
    }
    

    Synchronized 对象锁与类锁

    对象锁

    • 同一时间只能有一个线程获得实例对象锁的使用权,并执行该对象加锁的方法,其它线程必须等待该线程执行完锁内的方法才能抢占对象锁的使用权
    public class Main {
        public static void main(String[] args) {
            SyncTest s1 = new SyncTest();
            new Thread(()->s1.a()).start();
            new Thread(()->s1.b()).start();
        }
    
        public static class SyncTest {
    
            public synchronized void a() {
                try {
                    System.out.println(Thread.currentThread().getId() + ":--a--start  ,  " + System.currentTimeMillis());
                    TimeUnit.SECONDS.sleep(1);
                    System.out.println(Thread.currentThread().getId() + ":--a--end  ,  " + System.currentTimeMillis());
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
    
            public synchronized void b() {
                System.out.println(Thread.currentThread().getId() + ":--b--start  ,  " + System.currentTimeMillis());
            }
            
            public void c() {
                System.out.println(Thread.currentThread().getId() + ":--b--start  ,  " + System.currentTimeMillis());
            }
        }
    }
    
    • 未加锁方法不受影响,其它线程仍可以调用该对象其它未加锁的方法
    SyncTest s1 = new SyncTest();
    new Thread(()->s1.a()).start();
    new Thread(()->s1.c()).start();
    }
    
    • 类的不同实例对象之间互相不影响
    SyncTest s1 = new SyncTest();
    SyncTest s2 = new SyncTest();
    new Thread(()->s1.a()).start();
    new Thread(()->s2.a()).start();
    

    类锁

    • 两个线程同时访问不同对象的类锁静态方法,会发生阻塞竞争
    public class Main {
        public static void main(String[] args) {
            SyncTest s1 = new SyncTest();
            SyncTest s2 = new SyncTest();
            new Thread(()->s1.a()).start();
            new Thread(()->s2.a()).start();
        }
    
        public static class SyncTest {
    
            public static synchronized void a() {
                try {
                    System.out.println(Thread.currentThread().getId() + ":--a--start  ,  " + System.currentTimeMillis());
                    TimeUnit.SECONDS.sleep(1);
                    System.out.println(Thread.currentThread().getId() + ":--a--end  ,  " + System.currentTimeMillis());
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
    
            public synchronized void b() {
                System.out.println(Thread.currentThread().getId() + ":--b--start  ,  " + System.currentTimeMillis());
            }
        }
    }
    
    • 但访问非类锁方法(即对象锁的方法)时,不会发生竞争与阻塞
    SyncTest s1 = new SyncTest();
    SyncTest s2 = new SyncTest();
    new Thread(()->s1.a()).start();
    new Thread(()->s2.b()).start();
    

    相关文章

      网友评论

        本文标题:Java 多线程(三):Synchronized 详解

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