Java synchronized 用法

来源:互联网 发布:淘宝网店经营 编辑:程序博客网 时间:2024/06/03 02:37

1. synchronized 是JAVA关键字,可修饰方法和方法块。synchronized 的作用包括两方面:

1.1  多线程环境下的同步,多个线程互斥的访问同一个对象。

1.2 某个线程改变对象属性后,其他线程可及时获知该改变。


2. 在多线程环境中,同步方法被访问时,该类的非同步方法可以被访问;

非静态同步方法被访问时,同一实例的非静态方法不可被访问,静态同步方法可以被访问,非同一实例的非静态同步方法也可以被访问;

静态同步方法被访问时,该类的静态同步方法不可被访问,非静态同步方法可以被访问。

程序示例:

代码2-1

public class SynchronizedTest {public synchronized static void staticA() {int i = 0;while (i++ < 5) {System.out.println(Thread.currentThread().getName() + " staticA");try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}}}public static void staticB() {synchronized (SynchronizedTest.class) {int i = 0;while (i++ < 5) {System.out.println(Thread.currentThread().getName()+ " staticB");try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}}}}public synchronized void funA() {int i = 0;while (i++ < 5) {System.out.println(Thread.currentThread().getName() + " funA");try {Thread.sleep(400);} catch (InterruptedException e) {e.printStackTrace();}}}public void funB() {synchronized (this) {int i = 0;while (i++ < 5) {System.out.println(Thread.currentThread().getName() + " funB");try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}}}}}

在代码2-1 中共包含四个方法,其中 staticA(), 和staticB () 方法以类(SynchronizedTest.class)为锁,fun A() 和funB() 以调用该方法的对象为锁。

下面以几个例子来说明 被 synchronized 关键字修饰的方法和关键字在多线程环境下的访问。

2.1  访问类的同步静态方法是,该类的其他静态同步方法不可被同时访问,非静态方法,同步非静态方法可以被同时访问。

代码2.1

<span style="white-space:pre"></span>public static void main(String[] args) {final SynchronizedTest ta = new SynchronizedTest();// final SynchronizedTest tb = new SynchronizedTest();Thread t1 = new Thread(new Runnable() {@Overridepublic void run() {ta.staticB();}}, "t1");Thread t2 = new Thread(new Runnable() {@Overridepublic void run() {ta.staticA();}}, "t2");t1.start();t2.start();}
代码2-2 的输出为:

t1 staticB
t1 staticB
t1 staticB
t1 staticB
t1 staticB
t2 staticA
t2 staticA
t2 staticA
t2 staticA
t2 staticA

staticA() 和staticB() 以类(SynchronizedTest.class)为锁,静态方法属于类方法,因此当访问某个同步静态方法被访问时,该类中其他的静态同步方法都不可访问。

代码2-3

public static void main(String[] args) {final SynchronizedTest ta = new SynchronizedTest();// final SynchronizedTest tb = new SynchronizedTest();Thread t1 = new Thread(new Runnable() {@Overridepublic void run() {ta.funA();}}, "t1");Thread t2 = new Thread(new Runnable() {@Overridepublic void run() {ta.staticA();}}, "t2");t1.start();t2.start();}
输出为:

t1 funA
t2 staticA
t1 funA
t2 staticA
t1 funA
t2 staticA
t1 funA
t2 staticA
t1 funA
t2 staticA

funA() 以调用它的对象ta为锁,staticA() 以类SynchronizedTest.class 为锁,在多线程环境下上述两个方法的访问互不影响,可以同时访问。

2.2  同步非静态方法被访问时,同一实例对象中的其他同步非静态方法不可以被访问。

代码2-3

public static void main(String[] args) {final SynchronizedTest ta = new SynchronizedTest();// final SynchronizedTest tb = new SynchronizedTest();Thread t1 = new Thread(new Runnable() {@Overridepublic void run() {ta.funA();}}, "t1");Thread t2 = new Thread(new Runnable() {@Overridepublic void run() {ta.funB();}}, "t2");t1.start();t2.start();}
输出:

t1 funA
t1 funA
t1 funA
t1 funA
t1 funA
t2 funB
t2 funB
t2 funB
t2 funB
t2 funB

funA() 和 funB() 均以对象ta为锁,因此在多线程环境下不能被同时访问。

2.3  同一个类的不同实例中,静态同步方法不可用被同时访问,非静态同步方法可以被同时访问。

public static void main(String[] args) {final SynchronizedTest ta = new SynchronizedTest();final SynchronizedTest tb = new SynchronizedTest();Thread t1 = new Thread(new Runnable() {@Overridepublic void run() {tb.funA();}}, "t1");Thread t2 = new Thread(new Runnable() {@Overridepublic void run() {ta.funA();}}, "t2");t1.start();t2.start();}
输出:

t2 funA
t1 funA
t2 funA
t1 funA
t2 funA
t1 funA
t1 funA
t2 funA
t1 funA
t2 funA

非静态同步方法以调用它的对象为锁,因此类的不同实例可以同时访问该方法。

静态同步方法以类为锁,因此即便是类的不同实例也不可以同时访问静态同步方法。














0 0
原创粉丝点击