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中的一个同步方

时间: 2024-10-09 02:05:58

synchronized(this)的相关文章

JAVA synchronized关键字锁机制(中)

synchronized 锁机制简单的用法,高效的执行效率使成为解决线程安全的首选. 下面总结其特性以及使用技巧,加深对其理解. 特性: 1. Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码.       2. 当一个线程同时访问object的一个synchronized(this)同步代码块时,其它线程仍然可以访问非修饰的方法或代码块.       3. 当多个线程同时访问object的synchronized(this)同步代码

jgs--多线程和synchronized

多线程 多线程是我们开发人员经常提到的一个名词.为什么会有多线程的概念呢?我们的电脑有可能会有多个cpu(或者CPU有多个内核)这就产生了多个线程.对于单个CPU来说,由于CPU运算很快,我们在电脑上运行多个软件时,每个软件在CPU上运行很短的时间就会切换成其他软件.由于来回切换的时间很短,我们感觉好像所有的程序都在同时运行,这也是多线程.多线程可以解决较多的用户访问同一个服务时压力过大的问题,可以更充分的利用计算机的性能. 多线程的问题 多线程的好处很多,可是相应的也出现了一些问题.其中最常见

HashMap,Hashtable,ConcurrentHashMap 和 synchronized Map 的原理和区别

HashMap 是否是线程安全的,如何在线程安全的前提下使用 HashMap,其实也就是HashMap,Hashtable,ConcurrentHashMap 和 synchronized Map 的原理和区别.当时有些紧张只是简单说了下HashMap不是线程安全的:Hashtable 线程安全,但效率低,因为是 Hashtable 是使用 synchronized 的,所有线程竞争同一把锁:而 ConcurrentHashMap 不仅线程安全而且效率高,因为它包含一个 segment 数组,将

Java synchronized的实现原理与应用

在多线程中synchronized应该是我们运用的最多的,很多人会称呼它为重量级锁.java中的每一个对象都可以作为锁.具体表现为以下三种形式. 对于普通同步方法,锁是当前实例对象. //图书 class Books { private int id;// 图书ID private String name; // 图书名称 private int number; // 图书数量 //存书 public void stockBooks(int count) { number+=count; try

java中的synchronized关键字

参考:http://www.cnblogs.com/devinzhang/archive/2011/12/14/2287675.html 多线程问题的根因: 多线程环境下,对一个对象更改的时候,一个线程A对某个变量做了改变,但是还没改变完成能,就被另外一个线程B抢去了cpu,那么A就不会再执行了,因此导致了数据不一致行为.针对上面引文中银行取款存款的例子,本来存一百取一百正好抵消,但是由于多线程的之间的肆意抢占,有些取存款的操作没有完成,自然导致结果千奇百怪. 关键点: synchronized

【Java并发编程】之七:使用synchronized获取互斥锁的几点说明

 在并发编程中,多线程同时并发访问的资源叫做临界资源,当多个线程同时访问对象并要求操作相同资源时,分割了原子操作就有可能出现数据的不一致或数据不完整的情况,为避免这种情况的发生,我们会采取同步机制,以确保在某一时刻,方法内只允许有一个线程. 采用synchronized修饰符实现的同步机制叫做互斥锁机制,它所获得的锁叫做互斥锁.每个对象都有一个monitor(锁标记),当线程拥有这个锁标记时才能访问这个资源,没有锁标记便进入锁池.任何一个对象系统都会为其创建一个互斥锁,这个锁是为了分配给线程的,

关于synchronized

如果用synchronized修饰一个类成员方法A,那么就不会出现下面的情况: 同时多个线程访问这个类的A方法. 当然如果还有一个方法B,它没有被synchronized修饰,那么A方法与B方法是可以并行执行的.如下: package thread; public class SyncTest implements Runnable { public synchronized void m1() throws Exception{ System.out.println("m1开始");

Java synchronized 总结

在Java开发的时候经常会用到关键字synchronized来对代码进行同步,在使用的过程中,对于synchronized确不是很熟悉,最近在看Spring源码时,发现有不少地方都用到同步,因此,趁此机会,研究一下. 1. synchronized锁的对象 Java中的每一个对象都可以作为锁. 1)对于同步方法,锁是当前实例对象. 2)对于静态同步方法,锁是当前对象的Class对象.因为在Java 虚拟机中一个类只能对应一个类对象,所以同时只允许一个线程执行同一个类中的静态同步方法. 3)对于同

Java synchronized详解

Java synchronized详解 第一篇: 使用synchronized 在编写一个类时,如果该类中的代码可能运行于多线程环境下,那么就要考虑同步的问题.在Java中内置了语言级的同步原语--synchronized,这也大大简化了Java中多线程同步的使用.我们首先编写一个非常简单的多线程的程序,是模拟银行中的多个线程同时对同一个储蓄账户进行存款.取款操作的. 在程序中我们使用了一个简化版本的Account类,代表了一个银行账户的信息.在主程序中我们首先生成了1000个线程,然后启动它们

synchronized 和 lock 的区别

lock更灵活,可以自由定义多把锁的加锁解锁顺序(synchronized要按照先加的后解顺序) 提供多种加锁方案,lock 阻塞式, trylock 无阻塞式, lockInterruptily 可打断式, 还有trylock的带超时时间版本. 本质上和监视器锁(即synchronized是一样的) 能力越大,责任越大,必须控制好加锁和解锁,否则会导致灾难. 和Condition类的结合.