对synchronized(this)的一些理解

对synchronized(this)的一些理解

一、当两个并发线程访问同一个对象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中的一个同步方法。

t1 : Inner.m4t1()=4
t1 : Inner.m4t1()=3
t1 : Inner.m4t1()=2
t1 : Inner.m4t1()=1
t1 : Inner.m4t1()=0
t2 : Inner.m4t2()=4
t2 : Inner.m4t2()=3
t2 : Inner.m4t2()=2
t2 : Inner.m4t2()=1
t2 : Inner.m4t2()=0

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/100541.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号