Java synchronized使用

先看测试方法:

package com.vincent;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * Vincent 创建于 2016/5/11.
 */
public class Main {
    public static void main(String[] args) {
        ExecutorService threadPool = Executors.newCachedThreadPool();
        final SynchronizedDemo synchronizedDemo=new SynchronizedDemo();
        for (int i=0;i<5;i++){
            threadPool.execute(new Runnable() {
                public void run() {
                    synchronizedDemo.b();
                }
            });
        }
        for (int i=0;i<3;i++){
            threadPool.execute(new Runnable() {
                public void run() {
                    synchronizedDemo.a();
                }
            });

        }
    }
}
  • 多个线程同时访问多个synchronized方法:
package com.vincent;

import java.util.concurrent.TimeUnit;

/**
 * Vincent 创建于 2016/5/11.
 */
public class SynchronizedDemo {

    private Object lock1 = new Object();
    private Object lock2 = new Object();

    long currentTimeMillis = System.currentTimeMillis();

    public synchronized void a() {
        long num = System.currentTimeMillis() - currentTimeMillis;
        System.out.println("a.num=" + num);
        try {
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public synchronized void b() {
        long num = System.currentTimeMillis() - currentTimeMillis;

        System.out.println("b.num=" + num);
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

输出如下:

b.num=2
a.num=1003
a.num=3003
a.num=5004
b.num=7004
b.num=8004
b.num=9004
b.num=10004

由此可以看出:多线程在同一时刻只能有一个线程访问对象的synchronized方法

  • 多线程同时访问一个synchronized方法,一个非synchronized方法
package com.vincent;

import java.util.concurrent.TimeUnit;

/**
 * Vincent 创建于 2016/5/11.
 */
public class SynchronizedDemo {

    private Object lock1 = new Object();
    private Object lock2 = new Object();

    long currentTimeMillis = System.currentTimeMillis();

    public synchronized void a() {
        long num = System.currentTimeMillis() - currentTimeMillis;
        System.out.println("a.num=" + num);
        try {
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public void b() {
        long num = System.currentTimeMillis() - currentTimeMillis;

        System.out.println("b.num=" + num);
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

输出:

b.num=15
b.num=16
a.num=16
b.num=16
b.num=16
b.num=16
a.num=2016
a.num=4016

由此看出:如果有线程访问synchronized方法,其他线程访问非synchronized方法不受影响

  • 多线程同时访问多个synchronized关键字修饰的代码块
package com.vincent;

import java.util.concurrent.TimeUnit;

/**
 * Vincent 创建于 2016/5/11.
 */
public class SynchronizedDemo {

    private Object lock1 = new Object();
    private Object lock2 = new Object();

    long currentTimeMillis = System.currentTimeMillis();

    public void a() {
        synchronized (this) {
            long num = System.currentTimeMillis() - currentTimeMillis;
            System.out.println("a.num=" + num);
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public void b() {
        synchronized (this) {

            long num = System.currentTimeMillis() - currentTimeMillis;

            System.out.println("b.num=" + num);
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

}

输出:

b.num=1
a.num=1002
a.num=3002
a.num=5003
b.num=7003
b.num=8003
b.num=9003
b.num=10004

由此可以看出:该用法和示例1作用相同

  • synchronized修饰的代码块使用其他同一个对象加锁
package com.vincent;

import java.util.concurrent.TimeUnit;

/**
 * Vincent 创建于 2016/5/11.
 */
public class SynchronizedDemo {

    private Object lock1 = new Object();
    private Object lock2 = new Object();

    long currentTimeMillis = System.currentTimeMillis();

    public void a() {
        synchronized (lock1) {
            long num = System.currentTimeMillis() - currentTimeMillis;
            System.out.println("a.num=" + num);
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public void b() {
        synchronized (lock1) {

            long num = System.currentTimeMillis() - currentTimeMillis;

            System.out.println("b.num=" + num);
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

}

输出:

b.num=2
a.num=1003
b.num=3003
b.num=4004
b.num=5004
b.num=6004
a.num=7004
a.num=9004

结果同1

  • synchronized修饰的代码块使用其他不同对象加锁
package com.vincent;

import java.util.concurrent.TimeUnit;

/**
 * Vincent 创建于 2016/5/11.
 */
public class SynchronizedDemo {

    private Object lock1 = new Object();
    private Object lock2 = new Object();

    long currentTimeMillis = System.currentTimeMillis();

    public void a() {
        synchronized (lock1) {
            long num = System.currentTimeMillis() - currentTimeMillis;
            System.out.println("a.num=" + num);
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public void b() {
        synchronized (lock2) {

            long num = System.currentTimeMillis() - currentTimeMillis;

            System.out.println("b.num=" + num);
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

}

输出:

b.num=1
a.num=2
b.num=1002
b.num=2002
a.num=2003
b.num=3003
b.num=4003
a.num=4003

由此看出:访问a和b的线程互不影响

你可能感兴趣的:(Java synchronized使用)