对象中同时有2个方法使用synchorized修饰

问:当一个对象中有2个方法同时用synchronized修饰,那么当线程一在访问方法1时,其他线程是否可以访问方法二?

答案:由于对象的内置锁(监视器锁)是唯一的,所以当线程一在访问对象的方法1时,持有了该对象的内置锁,那么再线程一释放该内置锁之前,其他线程是无法获取该对象内置锁,所以其他线程无法访问方法二。

验证一:只有方法一使用synchroized修饰时,其他线程可以随意访问方法二。

/**
 * 我们测试,如果统一个对象,有2个方法都使用synchronized。
 * 验证:每个对象有唯一的对象锁;(称为:内置锁或监视器锁)
 * 那么当线程一在访问方法一时,已经持有方法该对象锁。
 * 其他线程若想执行方法二,必须等待线程一释放该对象锁。
 * @Author: dhcao
 * @Version: 1.0
 */
public class SynchronizedFac {

    public synchronized void methodOne() throws Exception {
        String threadName = Thread.currentThread().getName();
        Thread.sleep(3000);
        System.out.println(threadName + "  执行方法1");
    }

    /**
     * 第一次测试,方法二不加锁,我们预期:
     * 当线程一执行方法1时,其他线程是可以访问方法二的。
     */
    public void methodTwo() {
        String threadName = Thread.currentThread().getName();
        System.out.println(threadName + "  执行方法2");
    }


    public static void main(String[] args) throws Exception{
                // 保证对象相同
        final SynchronizedFac fac = new SynchronizedFac();

        for (int i = 0; i < 5; i++) {
            // 我们让线程一来访问方法一
            if (i == 0) {
                new Thread(new Runnable() {
                    public void run() {
                        try {
                            fac.methodOne();
                        } catch (Exception e) {
                            e.printStackTrace();
                        }

                    }
                }, "thread -- " + i).start();
            }else{
                // 其他线程则访问方法二
                new Thread(new Runnable() {
                    public void run() {
                        try {
                            fac.methodTwo();
                        } catch (Exception e) {
                            e.printStackTrace();
                        }

                    }
                }, "thread -- " + i).start();
            }

        }
    }
}

运行结果:由于方法1中有线程等待,所以其他线程率先执行完了方法二

thread -- 1 执行方法2
thread -- 2 执行方法2
thread -- 3 执行方法2
thread -- 4 执行方法2
thread -- 0 执行方法1

验证二:方法一和方法二同时使用synchroized修饰时,必须等线程一释放对象锁之后其他线程才能获取锁访问方法二。

package org.dhcao.relax.synchronizedOneInstance;

/**
 * 我们测试,如果统一个对象,有2个方法都使用synchronized。
 * 验证:每个对象有唯一的对象锁;(称为:内置锁或监视器锁)
 * 那么当线程一在访问方法一时,已经持有方法该对象锁。
 * 其他线程若想执行方法二,必须等待线程一释放该对象锁。
 * @Author: dhcao
 * @Version: 1.0
 */
public class SynchronizedFac {

    public synchronized void methodOne() throws Exception {
        String threadName = Thread.currentThread().getName();
        Thread.sleep(3000);
        System.out.println(threadName + "  执行方法1");
    }

    /**
     * 第二次测试,方法二加锁,我们预期:
     * 当线程一执行方法1时,其他线程是不可以访问方法二的;
     * 必须等待线程一释放锁
     */
    public synchronized void methodTwo() {
        String threadName = Thread.currentThread().getName();
        System.out.println(threadName + "  执行方法2");
    }


    public static void main(String[] args) throws Exception{

        final SynchronizedFac fac = new SynchronizedFac();

        for (int i = 0; i < 5; i++) {
            // 我们让线程一来访问方法一
            if (i == 0) {
                new Thread(new Runnable() {
                    public void run() {
                        try {
                            fac.methodOne();
                        } catch (Exception e) {
                            e.printStackTrace();
                        }

                    }
                }, "thread -- " + i).start();
            }else{
                // 其他线程则访问方法二
                new Thread(new Runnable() {
                    public void run() {
                        try {
                            fac.methodTwo();
                        } catch (Exception e) {
                            e.printStackTrace();
                        }

                    }
                }, "thread -- " + i).start();
            }

        }
    }
}

执行结果:在线程1(thread — 0)访问方法1时,该对象锁已经被线程一持有,则其他线程需等待该线程退出方法一,释放对象锁,才能进入被synchorized修饰的方法;

thread -- 0 执行方法1
thread -- 4 执行方法2
thread -- 3 执行方法2
thread -- 2 执行方法2
thread -- 1 执行方法2

猜你喜欢

转载自www.cnblogs.com/dhcao/p/11567002.html