Synchronized可分为synchronized方法和synchronized块。synchronized方法通常是在public之后返回值之前如:public synchronized void A()
而synchronized块则是在方法里面,如:
public void B(){
Synchronized(object){
……
}
}
一、两个线程并发访问synchronized块时,一次只有一个线程能够访问,另一个线程只能等待当前线程访问完并释放synchronized块才能访问。
/** * 这个例子是想说明两个并发执行的线程需要同时访问一个对象的synchronized代码块时,同一时刻只有一个进程在执行, * 一个线程在执行时,另一个线程必须等待当前线程执行完 * @author zzj * */ public class Thread1 extends Thread{ public static void main(String[] args) { Thread1 t1 = new Thread1();//注意这里,因为ta,tb是两个并发执行的线程 Thread ta = new Thread(t1,"A"); Thread tb = new Thread(t1,"B"); ta.start(); tb.start(); } public void run(){ synchronized(this){ for(int i=0;i<5;i++){ System.out.println(Thread.currentThread().getName()+"锁释放"+i); try { Thread.sleep(500); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } }
结果:
A锁释放0
A锁释放1
A锁释放2
A锁释放3
A锁释放4
B锁释放0
B锁释放1
B锁释放2
B锁释放3
B锁释放4
二、当一个线程访问synchronized块时,另一个线程仍可以访问该object的非synchronized同步代码块
/** * 这个例子是要说明一个线程访问object的synchronized同步代码块时,其他线程可以同时访问object的非synchronized块 * @author zzj * */ public class Thread2{ public static void main(String[] args) { final Thread2 t2 = new Thread2();//注意这里,因为ta,tb是两个并发执行的线程 Thread ta = new Thread(new Runnable(){public void run(){ t2.A();}},"A"); Thread tb = new Thread(new Runnable(){public void run(){ t2.B();}},"B"); ta.start(); tb.start(); } //synchronized方法 public void A(){ synchronized(this){ for(int i=0;i<5;i++){ System.out.println(Thread.currentThread().getName()+":"+i); try { Thread.sleep(500); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } //非synchronized方法 public void B(){ for(int i=0;i<5;i++){ System.out.println(Thread.currentThread().getName()+":"+i); try { Thread.sleep(500); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
结果:
A:0
B:0
A:1
B:1
A:2
B:2
B:3
A:3
B:4
A:4
三、当一个线程访问object的synchronized同步代码部分时,其他线程对object的其他synchronized代码块的访问也讲被阻塞。也就是说,一个线程获得这个对象锁时,就把这个对象锁起来了,其他线程不能再访问这个对象的其他同步方法,但是这是比较笼统的做法,事实上,我们其他进程可能要短暂地访问其他带锁资源,这时,我们就可以使用虚拟对象来上锁:
/** * 这个例子是想说明两个并发的线程如果一个在访问synchronized同步代码块,其他线程对所有其他sychronized块的访问会被阻塞 * @author zzj * */ public class Thread3 extends Thread{ public static void main(String[] args) { final Thread3 t3 = new Thread3();//注意这里,因为ta,tb是两个并发执行的线程 Thread ta = new Thread(new Runnable(){public void run(){ t3.A();}},"A"); Thread tb = new Thread(new Runnable(){public void run(){ t3.B();}},"B"); ta.start(); tb.start(); } //synchronized代码块 public void A(){ synchronized(this){ for(int i=0;i<5;i++){ System.out.println(Thread.currentThread().getName()+":"+i); try { Thread.sleep(500); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } //非synchronized代码块 public void B(){ synchronized(this){ for(int i=0;i<5;i++){ System.out.println(Thread.currentThread().getName()+":"+i); try { Thread.sleep(500); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } }
结果:
A:0
A:1
A:2
A:3
A:4
B:0
B:1
B:2
B:3
B:4
四、当一个线程访问object的一个synchronized同步代码块时,它就获得了同步对象锁,其他所有线程对该object对象的所有同步代码部分访问都暂时被阻塞
/** * 这个例子是想说明一个线程在执行synchronized同步代码块时,其他线程要访问同步代码部分 * (不论是synchronized块还是方法都将被阻塞) * @author zzj * */ public class Thread4 { public static void main(String[] args) { final Thread4 t4 = new Thread4();//注意这里,因为ta,tb是两个并发执行的线程 Thread ta = new Thread(new Runnable(){public void run(){ t4.A();}},"A"); Thread tb = new Thread(new Runnable(){public void run(){ t4.B();}},"B"); ta.start(); tb.start(); } //synchronized代码块 public void A(){ synchronized(this){ for(int i=0;i<5;i++){ System.out.println(Thread.currentThread().getName()+":"+i); try { Thread.sleep(500); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } //非synchronized代码块 public synchronized void B(){ for(int i=0;i<5;i++){ System.out.println(Thread.currentThread().getName()+":"+i); try { Thread.sleep(500); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
结果:
A:0
A:1
A:2
A:3
A:4
B:0
B:1
B:2
B:3
B:4
五、以上规则对其他对象锁同样适用。
仔细看1,2,3,4的区别。
总的说来,synchronized关键字可以作为函数的修饰符,也可作为函数内的语句,也就是平时说的同步方法和同步语句块。如果再细的分类,synchronized可作用于instance变量、object reference(对象引用)、static函数和class literals(类名称字面常量)身上。
我们需要明确几点:
A.无论synchronized关键字加在方法上还是对象上,它取得的锁都是对象,而不是把一段代码或函数当作锁――而且同步方法很可能还会被其他线程的对象访问。
B.每个对象只有一个锁(lock)与之相关联。
C.实现同步是要很大的系统开销作为代价的,甚至可能造成死锁,所以尽量避免无谓的同步控制。
<!--EndFragment-->
相关推荐
在提供的压缩包文件`java_sychronization`中,可能包含了一些示例代码,用于演示如何在Java中使用`synchronized`关键字以及`wait()`和`notify()`方法。通过研究这些样例,你可以更深入地了解这些工具的用法和效果。...
这是一种防止死锁和资源泄露的好方法。 除了`std::lock_guard`,还可以使用`std::unique_lock`,它提供了更多的灵活性,比如可以手动解锁或者尝试不阻塞地获取锁。 C++还提供了一些其他的同步工具,如`std::...
在这篇文章中,我们将详细介绍 Java 中 synchronized 的使用方法,并通过实例代码来帮助大家更好地理解和学习。 一、使用场景 在实际开发中,synchronized 经常用于解决并发访问共享资源时的线程安全问题。例如,...
为了解决这个问题,我们可以使用双重检查锁机制来实现单例模式。 方式一:使用静态内部类 方式一使用静态内部类来实现单例模式。静态内部类可以确保单例对象的唯一性,因为静态内部类只会被加载一次,这样可以避免...
- 使用任务管理器检查是否有残留的Domino进程,并使用任务管理器终止这些进程(注意不要终止其他分区的进程)。 - 再次启动Domino服务器。 ##### 场景二:Domino启动后很快出现宕机并产生NSD(Non-Scheduled Dump...
ArrayList类和Vector类类似,但是ArrayList类不是线程同步的(sychronized),因此在多线程环境下需要小心使用。 Map接口 Map接口是JAVA中另一个常用的数据结构,它提供了键值对的存储和操作方法。Map接口的实现类有...
sychronized 关键字可以用于修饰方法和代码块两种形式。例如,在方法上使用 synchronized 关键字,可以保障该方法在同一时间只能被一个线程访问。例如: public synchronized void inc() { i++; } 在代码块上...
sychronized和Lock(ReentrantLock)之间的区别? sychoronized的自旋锁、偏向锁、轻量级锁、重量级锁、分别介绍和联系 threadLocal会发生内存泄漏吗?谈谈你对threadLocal的理解 为什么会发生内存泄漏? 对...
Sychronized 区别 Redis 分布式锁 Zookeeper 分布式锁 死锁产生原因 如何解决死锁 数据库死锁例子 JAVA 并发 AQS 源码 ReentrantLock 源码 Condition 源码 ConcurrentHashMap 源码 Java 线程状态 JAVA 数据结构 ...
本文主要探讨了一种创新的轴承故障诊断方法,结合了同步挤压S变换(Sychronized Squeeze Transform, SSST)和深度学习技术,特别是深度曲线波卷积神经网络(Deep Curvelet Convolutional Neural Network, DCCNN)。...
2.2.3. 本地方法区(线程私有) ................................................................................................................ 23 2.2.4. 堆(Heap-线程共享)-运行时数据区 .....................
本地方法区(线程私有) ................................................................................................................ 23 2.2.4. 堆(Heap-线程共享)-运行时数据区 ...........................
maven pom.xml 详解 格式为.xml格式
保护程序,电子加密狗!
这些组件常常一起使用,构建出强大的Web应用架构。例如,Spring和Hibernate可以协同工作,Spring负责整体控制,Hibernate处理数据持久化;Struts2作为前端控制器,处理HTTP请求,与后端服务进行交互;而静态资源和...