Java中synchronized关键字锁定的内容

Java中synchronized关键字锁定的内容

同步分为 同步方法 和 同步块 两种方式。
变量分为 实例变量(不带static的变量) 和 类变量(带static的变量)。

锁定类对象

【当锁定static变量的时候,由于static变量只有一份拷贝,所以此时锁定的也是类对象】

下面的写法都是锁定类对象。在下面的例子中是锁定的StaticSynchronized这个类。

测试代码:

package com.pkk.javaknow.synchronized_demo;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @author kunzai
 * @version V1.0
 * @Title: myknow
 * @Package com.pkk.javaknow.synchronized_demo
 * @Description: <静态类的锁的测试>
 * @date 2018/5/18 9:28
 */
public class StaticSynchronized {

    private static Object object = new Object();

    private static long sleepTime = 3000;

    public static synchronized void synchronizedMethod1() throws InterruptedException {
        System.out.println(Thread.currentThread().getName() + "synchronizedMethod1:is Run;" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
        Thread.sleep(sleepTime);
        System.out.println(Thread.currentThread().getName() + "synchronizedMethod1:is End;" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));

    }


    public static void synchronizedMethod2() throws InterruptedException {
        synchronized (StaticSynchronized.class) {
            System.out.println(Thread.currentThread().getName() + "synchronizedMethod2:is Run;" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
            Thread.sleep(sleepTime);
            System.out.println(Thread.currentThread().getName() + "synchronizedMethod2:is End;" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
        }
    }

    public static void synchronizedMethod3() throws InterruptedException {
        synchronized (object) {
            System.out.println(Thread.currentThread().getName() + "synchronizedMethod3:is Run;" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
            Thread.sleep(sleepTime);
            System.out.println(Thread.currentThread().getName() + "synchronizedMethod3:is End;" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
        }
    }

    public static void synchronizedMethod4() throws ClassNotFoundException, InterruptedException {
        synchronized (Class.forName("com.pkk.javaknow.synchronized_demo.StaticSynchronized")) {
            System.out.println(Thread.currentThread().getName() + "synchronizedMethod4:is Run;" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
            Thread.sleep(sleepTime);
            System.out.println(Thread.currentThread().getName() + "synchronizedMethod4:is End;" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
        }
    }

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

        /**
         * 核心线程数--不受超时时间影响-一直存在
         */
        int corePoolSize = 2;
        /**
         *最大线程数--当队列为LinkedBlockingDeque时,LinkedBlockingDeque根本不受最大线程数影响,超出会加入队列中,如果设置了队列数限制(本次设置为10),超过报错
         */
        int maximumPoolSize = 6;
        /**
         * 超时时间,新创建的不在核心线程中的超过5秒就清除掉
         */
        long keepAliveTime = 5;
        /**
         * 最大等待队列数
         */
        int maxWaitQue = 10;
        /**
         * 执行次数
         */
        int forCnt = 3;

        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, TimeUnit.SECONDS, new LinkedBlockingDeque<Runnable>(maxWaitQue));
        for (int i = 0; i < forCnt; i++) {

            threadPoolExecutor.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        synchronizedMethod1();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });

            threadPoolExecutor.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        synchronizedMethod2();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });

            threadPoolExecutor.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        synchronizedMethod3();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });


            threadPoolExecutor.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        synchronizedMethod4();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } catch (ClassNotFoundException e) {
                        e.printStackTrace();
                    }
                }
            });

        }
        threadPoolExecutor.shutdown();
    }


}

测试结果:

pool-1-thread-1synchronizedMethod1:is Run;2018-05-18 14:58:55
pool-1-thread-1synchronizedMethod1:is End;2018-05-18 14:58:58
pool-1-thread-1synchronizedMethod3:is Run;2018-05-18 14:58:58
pool-1-thread-2synchronizedMethod2:is Run;2018-05-18 14:58:58
pool-1-thread-1synchronizedMethod3:is End;2018-05-18 14:59:01
pool-1-thread-2synchronizedMethod2:is End;2018-05-18 14:59:01
pool-1-thread-2synchronizedMethod1:is Run;2018-05-18 14:59:01
pool-1-thread-2synchronizedMethod1:is End;2018-05-18 14:59:04
pool-1-thread-2synchronizedMethod2:is Run;2018-05-18 14:59:04
pool-1-thread-2synchronizedMethod2:is End;2018-05-18 14:59:07
pool-1-thread-2synchronizedMethod3:is Run;2018-05-18 14:59:07
pool-1-thread-1synchronizedMethod4:is Run;2018-05-18 14:59:07
pool-1-thread-2synchronizedMethod3:is End;2018-05-18 14:59:10
pool-1-thread-1synchronizedMethod4:is End;2018-05-18 14:59:10
pool-1-thread-2synchronizedMethod4:is Run;2018-05-18 14:59:10
pool-1-thread-2synchronizedMethod4:is End;2018-05-18 14:59:13
pool-1-thread-2synchronizedMethod2:is Run;2018-05-18 14:59:13
pool-1-thread-2synchronizedMethod2:is End;2018-05-18 14:59:16
pool-1-thread-2synchronizedMethod3:is Run;2018-05-18 14:59:16
pool-1-thread-1synchronizedMethod1:is Run;2018-05-18 14:59:16
pool-1-thread-2synchronizedMethod3:is End;2018-05-18 14:59:19
pool-1-thread-1synchronizedMethod1:is End;2018-05-18 14:59:19
pool-1-thread-2synchronizedMethod4:is Run;2018-05-18 14:59:19
pool-1-thread-2synchronizedMethod4:is End;2018-05-18 14:59:22

总结:

从上面测试结果可以看出,方法三是可以和其他三个方法中的任何一个方法并行执行,因为方法三锁定的是Object这个静态类对象而不是锁定的StaticSynchronized类,他们挣得不是同一个锁,所以可以并行执行,但是方法1和2和4中任何一个方法不可以并行执行,因为他们锁定的是StaticSynchronized类对象,这个没有释放,另一个不可以执行。

这种情况下,如果有一个线程thread 访问了这3个方法中的任何一个, 在同一时间内其它的线程都不能访问这3个方法。(注意,在这类里面方法3中锁定的是object对象,不是本类对象。)

总结一下:

synchronized可以修饰方法,可以修饰变量,方法和变量都可以是静态的【类方法类变量】,或者是非静态【实例方法实例变量】的。

锁定方法

锁定实例对象

synchronized锁住的是括号里的对象,而不是代码。对于非static的synchronized方法,锁的就是对象本身也就是this。

同步方法不会影响该类中的其他方法去执行

测试代码

package com.pkk.javaknow.synchronized_demo;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @author peikunkun
 * @version V1.0
 * @Title: myknow
 * @Package com.pkk.javaknow.synchronized_demo
 * @Description: <方法锁>
 * @date 2018/5/18 11:55
 */
public class MethodSynchronized {


    private static long sleepTime = 3000;

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

        /**
         * 核心线程数--不受超时时间影响-一直存在
         */
        int corePoolSize = 2;
        /**
         *最大线程数--当队列为LinkedBlockingDeque时,LinkedBlockingDeque根本不受最大线程数影响,超出会加入队列中,如果设置了队列数限制(本次设置为10),超过报错
         */
        int maximumPoolSize = 6;
        /**
         * 超时时间,新创建的不在核心线程中的超过5秒就清除掉
         */
        long keepAliveTime = 5;
        /**
         * 最大等待队列数
         */
        int maxWaitQue = 10;
        /**
         * 执行次数
         */
        int forCnt = 1;

        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, TimeUnit.SECONDS, new LinkedBlockingDeque<Runnable>(maxWaitQue));

        for (int i = 0; i < forCnt; i++) {
            MethodSynchronized methodSynchronized = new MethodSynchronized();


            threadPoolExecutor.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        methodSynchronized.methodSynchronized3();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });

            threadPoolExecutor.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        methodSynchronized.methodSynchronized2();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });

            threadPoolExecutor.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        methodSynchronized.methodSynchronized1();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });

        }
        threadPoolExecutor.shutdown();
    }

    public synchronized void methodSynchronized1() throws InterruptedException {
        System.out.println(Thread.currentThread().getName() + "methodSynchronized1:is Run;" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
        Thread.sleep(sleepTime);
        System.out.println(Thread.currentThread().getName() + "methodSynchronized1:is End;" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
    }

    public void methodSynchronized3() throws InterruptedException {
        System.out.println(Thread.currentThread().getName() + "methodSynchronized3:is Run;" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
        Thread.sleep(sleepTime);
        System.out.println(Thread.currentThread().getName() + "methodSynchronized3:is End;" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
    }

    public void methodSynchronized2() throws InterruptedException {
        synchronized (this) {
            System.out.println(Thread.currentThread().getName() + "methodSynchronized2:is Run;" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
            Thread.sleep(sleepTime);
            System.out.println(Thread.currentThread().getName() + "methodSynchronized2:is End;" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
        }
    }
}

运行结果:

pool-1-thread-1methodSynchronized3:is Run;2018-05-18 17:12:30
pool-1-thread-2methodSynchronized2:is Run;2018-05-18 17:12:30
pool-1-thread-1methodSynchronized3:is End;2018-05-18 17:12:33
pool-1-thread-2methodSynchronized2:is End;2018-05-18 17:12:33
pool-1-thread-1methodSynchronized1:is Run;2018-05-18 17:12:33
pool-1-thread-1methodSynchronized1:is End;2018-05-18 17:12:36

可以看出,不带同步的方法和一个同步的方法可以同时执行,但是此时锁定了本对象,另一个带有同步的方法就不可以执行,需要等待这个所释放之后才可以执行。

总结

也就是说synchronize修饰的方法和 synchronize(this) 都是锁住自己本身的对象 而synchronized(*.class)是锁住加载类对象,synchronized(object)是锁住object对象吧

猜你喜欢

转载自blog.csdn.net/a656678879/article/details/80364937