美文网首页
静态锁与对象锁

静态锁与对象锁

作者: gczxbb | 来源:发表于2019-08-03 12:18 被阅读0次

    一、对象锁

    synchronized关键字修饰普通方法或者方法中代码块。防止多线程中同一个实例同时访问该对象的方法。锁的是实例对象。
    创建一个TestSynchronized类,syncA()方法。

    public class TestSynchronized {
        //1对象锁
        public void syncA() {
            String threadName = Thread.currentThread().getName();
            synchronized (this) {
                Log.d(TAG, threadName + "线程, start syncA()方法。");
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                }
                Log.d(TAG, threadName + "线程, end syncA()方法。");
            }
        }
    
    }
    

    启动两个线程,创建两个对象,执行syncA方法。

    new Thread(new Runnable() {
        public void run() {
            new TestSynchronized().syncA();
        }
    }).start();
    new Thread(new Runnable() {
        public void run() {
            new TestSynchronized().syncA();
        }
    }).start();
    

    线程运行syncA方法时,并未因为synchronized同步竞争锁导致休眠,因为加锁的是各自的对象,不是类。synchronized关键字可以直接修饰syncA方法,如果改一下代码。

    final TestSynchronized sro = new TestSynchronized();
    new Thread(new Runnable() {
        public void run() {
            sro.syncA();
        }
    }).start();
    new Thread(new Runnable() {
        public void run() {
            sro.syncA();
        }
    }).start();
    

    一个对象,两个线程并发调用syncA()方法,竞争锁休眠,锁就是创建的对象本身。
    增加一个synchronized关键字修饰的方法syncB(),第二个线程执行syncB()方法。

    //2对象锁
    public synchronized void syncB() {
        String threadName = Thread.currentThread().getName();
        Log.d(TAG, threadName + "线程, start syncA()方法。");
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
        }
        Log.d(TAG, threadName + "线程, end syncA()方法。");
    }
    

    同一个对象,两个线程,执行syncA()和syncB()方法,竞争锁休眠。

    实例对象被lock,只能有一个线程进入该对象某个synchronized方法的代码块,其他线程无法进入任何synchronized同步方法。
    同步代码块和同步方法,同步方法默认以当前对象作为锁,静态方法以当前class作为锁。同步代码块是可能引起线程问题的一段代码,而不是整个方法,可以选择锁的内容。
    普通对象锁,不同对象,可同时访问。相同对象,不同加锁代码,不可同时访问。


    二、静态锁

    synchronized关键字修饰的静态方法或代码块锁是class类型,防止多线程中多个对象或类同时访问该类中的synchronized static方法,锁的是类对象。

    public class TestSynchronized {
        //1对象锁
        public void syncA() {
            String threadName = Thread.currentThread().getName();
            synchronized (TestSynchronized.class) {
                Log.d(TAG, threadName + "线程, start syncA()方法。");
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                }
                Log.d(TAG, threadName + "线程, end syncA()方法。");
            }
        }
    
    }
    

    将syncA()加上static关键字,静态方法,或者synchronized代码块将this改成TestSynchronized.class,创建两个对象,两个线程并发,执行syncA()方法,因为加的锁是类,两个方法会竞争锁。

    new Thread(new Runnable() {
        public void run() {
            new TestSynchronized().syncStaticA();
        }
    }).start();
    new Thread(new Runnable() {
        public void run() {
            TestSynchronized.syncStaticB();
        }
    }).start();
    

    两个线程,一个是对象执行同步静态syncStaticA()方法,一个是类执行同步静态syncStaticB()方法,加类锁,线程会竞争锁。

    如果类对象被lock,只能有一个线程进入该类某个synchronized方法的代码块,其他线程无法进入任何synchronized同步方法。
    静态锁,不同对象,相同方法及不同加锁代码块,都不能同时访问。
    普通锁和类锁两种不同类型的锁,他们之间并发时不会相互产生竞争,比如一个类两个方法分别上对象锁和类锁,创建两个对象,分别执行两个方法时,锁不同,不会产生竞争。


    任重而道远

    相关文章

      网友评论

          本文标题:静态锁与对象锁

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