博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
对synchronized(this)的一些理解
阅读量:4221 次
发布时间:2019-05-26

本文共 4572 字,大约阅读时间需要 15 分钟。

一、当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。

二、然而,当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。
三、尤其关键的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。
四、第三个例子同样适用其它同步代码块。也就是说,当一个线程访问object的一个synchronized(this)同步代码块时,它就获得了这个object的对象锁。结果,其它线程对该object对象所有同步代码部分的访问都被暂时阻塞。
五、以上规则对其它对象锁同样适用.
举例说明:

 

 

一、当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。

 

 

 

package ths;public class Thread1 implements Runnable {	public void run() {		synchronized (this) {			for (int i = 0; i < 5; i++) {				System.out.println(Thread.currentThread().getName()						+ " synchronized loop " + i);			}		}	}	public static void main(String[] args) {		Thread1 t1 = new Thread1();		Thread ta = new Thread(t1, "A");		Thread tb = new Thread(t1, "B");		ta.start();		tb.start();	}}

 

 

 

结果:
A synchronized loop 0
A synchronized loop 1
A synchronized loop 2
A synchronized loop 3
A synchronized loop 4
B synchronized loop 0
B synchronized loop 1
B synchronized loop 2
B synchronized loop 3
B synchronized loop 4
二、然而,当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。

 

 

 

 

 

package ths;public class Thread2 {	public void m4t1() {		synchronized (this) {			int i = 5;			while (i-- > 0) {				System.out						.println(Thread.currentThread().getName() + " : " + i);				try {					Thread.sleep(500);				} catch (InterruptedException ie) {				}			}		}	}	public void m4t2() {		int i = 5;		while (i-- > 0) {			System.out.println(Thread.currentThread().getName() + " : " + i);			try {				Thread.sleep(500);			} catch (InterruptedException ie) {			}		}	}	public static void main(String[] args) {		final Thread2 myt2 = new Thread2();		Thread t1 = new Thread(new Runnable() {			public void run() {				myt2.m4t1();			}		}, "t1");		Thread t2 = new Thread(new Runnable() {			public void run() {				myt2.m4t2();			}		}, "t2");		t1.start();		t2.start();	}}

 

 

结果:

t1 : 4
t2 : 4
t1 : 3
t2 : 3
t1 : 2
t2 : 2
t1 : 1
t2 : 1
t1 : 0
t2 : 0

 

 

 

三、尤其关键的是,当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。

 

 

 

//修改Thread2.m4t2()方法:

 

public void m4t2() {		synchronized (this) {			int i = 5;			while (i-- > 0) {				System.out						.println(Thread.currentThread().getName() + " : " + i);				try {					Thread.sleep(500);				} catch (InterruptedException ie) {				}			}		}	}

结果:
t1 : 4
t1 : 3
t1 : 2
t1 : 1
t1 : 0
t2 : 4
t2 : 3
t2 : 2
t2 : 1
t2 : 0
四、第三个例子同样适用其它同步代码块。也就是说,当一个线程访问object的一个synchronized(this)同步代码块时,它就获得了这个object的对象锁。结果,其它线程对该object对象所有同步代码部分的访问都被暂时阻塞。
//修改Thread2.m4t2()方法如下:

 

public synchronized void m4t2() {		int i = 5;		while (i-- > 0) {			System.out.println(Thread.currentThread().getName() + " : " + i);			try {				Thread.sleep(500);			} catch (InterruptedException ie) {			}		}	}

结果:
t1 : 4
t1 : 3
t1 : 2
t1 : 1
t1 : 0
t2 : 4
t2 : 3
t2 : 2
t2 : 1
t2 : 0
五、以上规则对其它对象锁同样适用:

 

 

 

package ths;public class Thread3 {	class Inner {		private void m4t1() {			int i = 5;			while (i-- > 0) {				System.out.println(Thread.currentThread().getName()						+ " : Inner.m4t1()=" + i);				try {					Thread.sleep(500);				} catch (InterruptedException ie) {				}			}		}		private void m4t2() {			int i = 5;			while (i-- > 0) {				System.out.println(Thread.currentThread().getName()						+ " : Inner.m4t2()=" + i);				try {					Thread.sleep(500);				} catch (InterruptedException ie) {				}			}		}	}	private void m4t1(Inner inner) {		synchronized (inner) { // 使用对象锁			inner.m4t1();		}	}	private void m4t2(Inner inner) {		inner.m4t2();	}	public static void main(String[] args) {		final Thread3 myt3 = new Thread3();		final Inner inner = myt3.new Inner();		Thread t1 = new Thread(new Runnable() {			public void run() {				myt3.m4t1(inner);			}		}, "t1");		Thread t2 = new Thread(new Runnable() {			public void run() {				myt3.m4t2(inner);			}		}, "t2");		t1.start();		t2.start();	}}

 

结果:
尽管线程t1获得了对Inner的对象锁,但由于线程t2访问的是同一个Inner中的非同步部分。所以两个线程互不干扰。
t1 : Inner.m4t1()=4
t2 : Inner.m4t2()=4
t1 : Inner.m4t1()=3
t2 : Inner.m4t2()=3
t1 : Inner.m4t1()=2
t2 : Inner.m4t2()=2
t1 : Inner.m4t1()=1
t2 : Inner.m4t2()=1
t1 : Inner.m4t1()=0
t2 : Inner.m4t2()=0
现在在Inner.m4t2()前面加上synchronized:

 

 

private synchronized void m4t2() {		int i = 5;		while (i-- > 0) {			System.out.println(Thread.currentThread().getName()					+ " : Inner.m4t2()=" + i);			try {				Thread.sleep(500);			} catch (InterruptedException ie) {			}		}	}

结果:
尽管线程t1与t2访问了同一个Inner对象中两个毫不相关的部分,但因为t1先获得了对Inner的对象锁,所以t2对Inner.m4t2()的访问也被阻塞,因为m4t2()是Inner中的一个同步方

转载地址:http://nlemi.baihongyu.com/

你可能感兴趣的文章
osg中使用MatrixTransform来实现模型的平移/旋转/缩放
查看>>
(一) Qt Model/View 的简单说明
查看>>
(二)使用预定义模型 QStringListModel例子
查看>>
UVM:7.4.5 加入存储器
查看>>
UVM:7.5.1 期望值与镜像值
查看>>
UVM:7.5.2 常用操作及其对期望值和镜像值的影响
查看>>
UVM:7.6.1 检查后门访问中hdl 路径的sequence
查看>>
UVM:7.6.2 检查默认值的sequence
查看>>
UVM:7.7.1 使用reg_predictor
查看>>
UVM:7.7.2 使用UVM_PREDICT_DIRECT功能与mirror 操作
查看>>
UVM:7.7.3 寄存器模型的随机化与update
查看>>
UVM:7.7.4 扩展位宽
查看>>
UVM:7.8.1 get_root_blocks
查看>>
UVM:7.8.2 get_reg_by_offset 函数
查看>>
UVM:8.1.1 任务与函数的重载
查看>>
UVM:8.1.2 约束的重载
查看>>
UVM:8.2.2 重载的方式及种类
查看>>
UVM:8.2.3 复杂的重载
查看>>
UVM:8.2.4 factory 机制的调试
查看>>
UVM:8.3.1 重载transaction
查看>>