为了保证数据的一致性即实现线程的安全性,java虚拟机提供了同步和锁机制。synchronized关键字是最基本的互斥同步手段。除此之外,还可以使用java.util.concurrent包中的重入锁(ReentrantLock)来实现同步。相比synchronized,ReentrantLock增加了一些高级功能,主要有等待可中断、可实现公平锁、锁可以绑定多个条件等。
见SynchronizedDemo.java的源码理解synchronized
/** * Synchronized理解: * 根据如下4个例子总结如下: * Synchronized修饰的方法和Synchronized(this)修饰的代码块功能是一样的,当使用Synchronized修饰的方法或Synchronized(this)修饰的代码块被调用时,当前的实例对象被锁住,因此没有其他线程可以调用该实例对象的这个或任何其他的Synchronized修饰的方法和Synchronized(this)修饰的代码块 * static Synchronized修饰的方法和Synchronized(*.class)修饰的代码块功能是一样的,当使用static Synchronized修饰的方法或Synchronized(*.class)修饰的代码块被调用时,当前的类对象(例子中的是Sync.class对象)被锁住,因此没有其他线程可以调用同一个类的的这个或任何其他的static Synchronized修饰的方法和Synchronized(*.class)修饰的代码块 **/ public class SynchronizedDemo{ /** * 例1: * 同一个对象: * 当一个线程进入一个对象A的synchronized方法的同时,其它线程不能进入该对象的任何synchronized方法 **/ private void showSynchronizedResult1(){ final Sync testSync1 = new Sync(); Thread thread1 = new Thread(new Runnable(){ @Override public void run(){ testSync1.run1(); } }); Thread thread2 = new Thread(new Runnable(){ @Override public void run(){ testSync1.run2(); } }); thread1.start(); thread2.start(); } /** * 例2: * 同一个对象: * 当一个线程进入一个对象A的synchronized方法的同时,其它线程可以进入该对象的普通方法 **/ private void showSynchronizedResult2(){ final Sync testSync1 = new Sync(); Thread thread1 = new Thread(new Runnable(){ @Override public void run(){ testSync1.run1(); } }); Thread thread3 = new Thread(new Runnable(){ @Override public void run(){ testSync1.run3(); } }); thread1.start(); thread3.start(); } /** * 例3: * 不同对象 * 当一个线程进入一个对象A的synchronized方法的同时,其它线程可以进入其他对象的synchronized方法,互不影响 **/ private void showSynchronizedResult3(){ final Sync testSync1 = new Sync(); final Sync testSync2 = new Sync(); Thread thread1 = new Thread(new Runnable(){ @Override public void run(){ testSync1.run1(); } }); Thread thread2 = new Thread(new Runnable(){ @Override public void run(){ testSync2.run2(); } }); thread1.start(); thread2.start(); } /** * 例4: * 当一个线程进入一个static synchronized方法的同时,其它线程不可以进入任何的static synchronized方法 **/ private void showStaticSynchronizedResult4(){ Thread thread1 = new Thread(new Runnable(){ @Override public void run(){ Sync.run4(); } }); Thread thread2 = new Thread(new Runnable(){ @Override public void run(){ Sync.run5(); } }); thread1.start(); thread2.start(); } public static void main(String args[]){ // 例1:多线程下同一对象的多个Synchronized方法 new SynchronizedDemo().showSynchronizedResult1(); // 例2:多线程下同一对象的Synchronized方法和普通方法 //new SynchronizedDemo().showSynchronizedResult2(); // 例3:多线程下不同对象的Synchronized方法 //new SynchronizedDemo().showSynchronizedResult3(); // 例4:多线程下的多个static Synchronized方法 //new SynchronizedDemo().showStaticSynchronizedResult4(); } } class Sync{ public synchronized void run1(){ for (int i = 0; i < 5; i++){ System.out.println("execute run1"); sleepOneSec(); } } public synchronized void run2(){ for (int i = 0; i < 5; i++){ System.out.println("execute run2"); sleepOneSec(); } } public void run3(){ for (int i = 0; i < 5; i++){ System.out.println("execute run3"); sleepOneSec(); } } public static synchronized void run4(){ for (int i = 0; i < 5; i++){ System.out.println("execute run4"); sleepOneSec(); } } public static synchronized void run5(){ for (int i = 0; i < 5; i++){ System.out.println("execute run5"); sleepOneSec(); } } private static void sleepOneSec(){ try{ Thread.sleep(1000); }catch (InterruptedException e){ e.printStackTrace(); } } }
分类:
java
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· dotnet 源代码生成器分析器入门
· ASP.NET Core 模型验证消息的本地化新姿势
· 对象命名为何需要避免'-er'和'-or'后缀
· SQL Server如何跟踪自动统计信息更新?
· AI与.NET技术实操系列:使用Catalyst进行自然语言处理
· 官方的 MCP C# SDK:csharp-sdk
· 一款 .NET 开源、功能强大的远程连接管理工具,支持 RDP、VNC、SSH 等多种主流协议!
· 提示词工程师自白:我如何用一个技巧解放自己的生产力
· 一文搞懂MCP协议与Function Call的区别
· 如何不购买域名在云服务器上搭建HTTPS服务