讲解对象锁和关键字synchronized修饰方法

每个对象在出生的时候就有一把钥匙(监视器),那么被synchronized 修饰的方法相当于给方法加了一个锁,这个方法就可以进行同步,在多线程的时候,不会出现线程安全问题。 
下面通过一张图片进行讲解:

1.一张图片

图片看不清,请右键 ,新标页面打开查看大图

这里写图片描述

2.图片对应的代码


import java.util.Date;

/**
 * 测试的object类
 *
 * @author:dufy
 * @version:1.0.0
 * @date 2017/9/29
 * @email 742981086@qq.com
 */
public class ObjectTest {


    public synchronized  void methodA(){
        try {
            System.out.println("This is methodA ...." + Thread.currentThread().getName() + ": " + new Date());
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }

    public void methodB(){

        System.out.println("This is methodB ...." + Thread.currentThread().getName() + ": " + new Date());
    }

    public synchronized void methodC(){

        try {
            System.out.println("This is methodC ...." + Thread.currentThread().getName() + ": " + new Date());
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }


}
package com.dufy.concurrentcode;

/**
 * 测试线程类
 *
 * @author:dufy
 * @version:1.0.0
 * @date 2017/9/29
 * @email 742981086@qq.com
 */
public class ThreadTest extends Thread{

    public static void main(String[] args) {
        ObjectTest ot = new ObjectTest();
        Thread1 t1 = new Thread1(ot,"thread1");
        Thread2 t2 = new Thread2(ot,"thread2");
        Thread3 t3 = new Thread3(ot,"thread3");
        Thread4 t4 = new Thread4(ot,"thread4");
        t1.start();
        t2.start();
        t3.start();
        t4.start();
    }


    static class Thread1 extends Thread{
        private ObjectTest objectTest;

        public Thread1(ObjectTest objectTest,String name){
            setName(name);
            this.objectTest = objectTest;
        }
        @Override
        public void run() {
            super.run();
            objectTest.methodA();
        }
    }

    static class Thread2 extends Thread{
        private ObjectTest objectTest;

        public Thread2(ObjectTest objectTest,String name){
            setName(name);
            this.objectTest = objectTest;
        }
        @Override
        public void run() {
            super.run();
            objectTest.methodB();
        }
    }

    static class Thread3 extends Thread{
        private ObjectTest objectTest;

        public Thread3(ObjectTest objectTest,String name){
            setName(name);
            this.objectTest = objectTest;
        }
        @Override
        public void run() {
            super.run();
            objectTest.methodA();
        }
    }

    static class Thread4 extends Thread{
        private ObjectTest objectTest;

        public Thread4(ObjectTest objectTest,String name){
            setName(name);
            this.objectTest = objectTest;
        }
        @Override
        public void run() {
            super.run();
            objectTest.methodC();
        }
    }
}

 

运行结果:

This is methodB ....thread2: Fri Sep 29 23:21:17 CST 2017
This is methodA ....thread1: Fri Sep 29 23:21:17 CST 2017
This is methodC ....thread4: Fri Sep 29 23:21:18 CST 2017
This is methodA ....thread3: Fri Sep 29 23:21:21 CST 2017

注:运行的结果可能和上图讲的线程流程不同,没有关系,只要理解对象锁和synchronized的核心思想就好,线程的运行本来就是具有随机性这个特点。

3.总结

  1. 每个对象都有一把锁,关键字synchronized取得锁都是对象锁,而不是把一段代码或方法(函数)当做锁。
  2. 上图所示,哪个线程先执行带有synchronized关键字的宝坻装修公司方法,哪个线程就持有这个方法所属对象的钥匙。其他线程只能处于等待状态。
  3. 调用关键字synchronized声明的方法,一定是排队运行的。这才是使用synchronized关键字的作用,排队运行,如果有共享资源的话,那么共享资源的读取就是线程安全的。
  4. 如果一个线程持有 object的钥匙,那么其他线程可以访问object对象没有上锁的方法,也就是非synchronized类型的方法。

 

 

posted on 2017-09-30 14:19  微笑向暖  阅读(263)  评论(0)    收藏  举报

导航