java的synchronized有几种加锁方式
在Java中,synchronized关键字提供了内置的支持来实现同步访问共享资源,以避免并发问题。synchronized主要有三种加锁方式:
1.同步实例方法
当一个实例方法被声明为synchronized时,该方法将同一时间只能被一个线程访问。锁是当前对象实例(即this)。
public class SynchronizedInstanceMethod {
public synchronized void doSomething() {
// 同步代码块
// 同一时间只能有一个线程执行这里的代码
}
public static void main(String[] args) {
SynchronizedInstanceMethod obj = new SynchronizedInstanceMethod();
// 创建多个线程访问obj的doSomething方法,它们将串行执行
// ...
}
}
当我们创建了两个线程来并发地增加计数器,由于我们使用了synchronized,因此计数器的增加线程是安全的,即使两个线程都在尝试修改同一个共享变量。在同步实例方法中,锁分别是实例对象和类对象。
public class SynchronizedInstanceMethodExample {
private int count = 0;
// 同步实例方法,锁定的是当前对象的实例(this)
public synchronized void increment() {
count++;
System.out.println(Thread.currentThread().getName() + " incremented count to " + count);
}
public static void main(String[] args) {
final SynchronizedInstanceMethodExample example = new SynchronizedInstanceMethodExample();
// 创建两个线程来增加计数器
Thread thread1 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
example.increment();
}
}, "Thread-1");
Thread thread2 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
example.increment();
}
}, "Thread-2");
// 启动线程
thread1.start();
thread2.start();
// 等待线程完成
try {
thread1.join();
thread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
// 输出最终计数
System.out.println("Final count: " + example.count);
}
}
2.同步静态方法
当一个静态方法被声明为synchronized时,该方法将同一时间只能被一个线程访问。锁是Class对象,而不是实例对象。
public class SynchronizedStaticMethod {
public static synchronized void doSomethingStatic() {
// 同步代码块
// 同一时间只能有一个线程执行这里的代码
}
public static void main(String[] args) {
// 创建多个线程访问SynchronizedStaticMethod的doSomethingStatic方法,它们将串行执行
// ...
}
}
当我们创建了两个线程来并发地增加计数器,由于我们使用了synchronized,因此计数器的增加线程是安全的,即使两个线程都在尝试修改同一个共享变量。在同步静态方法中,锁分别也是实例对象和类对象。
public class SynchronizedStaticMethodExample {
private static int count = 0;
// 同步静态方法,锁定的是当前对象的类(Class)对象
public static synchronized void increment() {
count++;
System.out.println(Thread.currentThread().getName() + " incremented static count to " + count);
}
public static void main(String[] args) {
// 创建两个线程来增加计数器
Thread thread1 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
increment();
}
}, "Thread-1");
Thread thread2 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
increment();
}
}, "Thread-2");
// 启动线程...
// 等待线程完成...
// 输出最终计数...
// (与上面的例子类似,但省略了重复的代码)
}
}
3.同步代码块
我们可以使用synchronized关键字来定义一个代码块,而不是整个方法。在这种情况下,你可以指定要获取的锁对象。这提供了更细粒度的同步控制。
public class SynchronizedBlock {
private final Object lock = new Object(); // 用于同步的锁对象
public void doSomething() {
synchronized (lock) {
// 同步代码块
// 同一时间只有一个线程能够执行这里的代码
}
// 这里的代码不受同步代码块的约束
}
public static void main(String[] args) {
SynchronizedBlock obj = new SynchronizedBlock();
// 创建多个线程访问obj的doSomething方法,但只有在synchronized块中的代码将串行执行
// ...
}
}
在上面的SynchronizedBlock类中,我们创建了一个私有的Object实例lock作为锁对象。当线程进入synchronized (lock)块时,它会尝试获取lock对象的锁。如果锁已经被其他线程持有,那么该线程将被阻塞,直到锁被释放。
当我们创建了两个线程来并发地增加计数器,同步代码块的例子中,我们显式地指定了一个对象作为锁。
public class SynchronizedBlockExample {
private final Object lock = new Object(); // 用于同步的锁对象
private int count = 0;
// 同步代码块,指定了锁对象
public void increment() {
synchronized (lock) {
count++;
System.out.println(Thread.currentThread().getName() + " incremented count to " + count);
}
}
public static void main(String[] args) {
// 类似于上面的例子,但使用SynchronizedBlockExample的increment方法
// ...(省略了重复的代码)
}
}
注意:使用synchronized时应该尽量避免在持有锁的情况下执行耗时的操作,因为这会导致其他等待锁的线程长时间阻塞。同时,过度使用synchronized可能会导致性能下降,因为它会引入线程间的竞争和可能的上下文切换。在设计并发程序时,应该仔细考虑同步的粒度,并可能使用其他并发工具(如ReentrantLock、Semaphore、CountDownLatch等)来提供更细粒度的控制。
java的synchronized有几种加锁方式的更多相关文章
- 015-线程同步-synchronized几种加锁方式、Java对象头和Monitor、Mutex Lock、JDK1.6对synchronized锁的优化实现
一.synchronized概述基本使用 为确保共享变量不会出现并发问题,通常会对修改共享变量的代码块用synchronized加锁,确保同一时刻只有一个线程在修改共享变量,从而避免并发问题. syn ...
- 【转载】Redis的Java客户端Jedis的八种调用方式(事务、管道、分布式…)介绍
转载地址:http://blog.csdn.net/truong/article/details/46711045 关键字:Redis的Java客户端Jedis的八种调用方式(事务.管道.分布式…)介 ...
- Java多线程有哪几种实现方式? Java中的类如何保证线程安全? 请说明ThreadLocal的用法和适用场景
java的同步机制,大概是通过:1.synchronized:2.Object方法中的wait,notify:3.ThreadLocal机制来实现的, 其中synchronized有两种用法:1.对类 ...
- JAVA中单例模式的几种实现方式
1 线程不安全的实现方法 首先介绍java中最基本的单例模式实现方式,我们可以在一些初级的java书中看到.这种实现方法不是线程安全的,所以在项目实践中如果涉及到线程安全就不会使用这种方式.但是如果不 ...
- 使用java配置定时任务的几种配置方式及示例
Spring定时器,主要有两种实现方式,包括Java Timer定时和Quartz定时器! 1.Java Timer定时 首先继承java.util.TimerTask类实现run方法 package ...
- Java中String对象两种赋值方式的区别
本文修改于:https://www.zhihu.com/question/29884421/answer/113785601 前言:在java中,String有两种赋值方式,第一种是通过“字面量”赋值 ...
- 细说java中Map的两种迭代方式
曾经对java中迭代方式总是迷迷糊糊的,今天总算弄懂了.特意的总结了一下.基本是算是理解透彻了. 1.再说Map之前先说下Iterator: Iterator主要用于遍历(即迭代訪问)Collecti ...
- Java中Map的4种遍历方式
第一种方式:这是平常用的最多也最可取的一种遍历方式. for (Map.Entry<String, Object> entry : map.entrySet()) { System.out ...
- 基于Java的二叉树的三种遍历方式的递归与非递归实现
二叉树的遍历方式包括前序遍历.中序遍历和后序遍历,其实现方式包括递归实现和非递归实现. 前序遍历:根节点 | 左子树 | 右子树 中序遍历:左子树 | 根节点 | 右子树 后序遍历:左子树 | 右子树 ...
- Java线程池的四种创建方式
Java通过Executors提供四种线程池,分别为:newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程. newFix ...
随机推荐
- 报表格式太难?一文教你Excel融合分析
Excel是我们最经常使用的处理报表工具了,尤其是金融行业更是需要天天和报表打交道.但是Excel有一个问题,如果面对的数据庞杂,则处理起来就会相当麻烦,当需要从多个数据源获取数据来制作一个报表时,这 ...
- mysql迁移sqlServer和mybatisPlus下查询语句转换为SqlServer2008
mysql数据迁移sqlServer2008 mybatisPlus下查询语句转换 一.mysql数据迁移到sqlServer2008中(包括数据结构和数据) 最近公司项目需要使用sqlServer以 ...
- HarmonyOS课程体验官招募(第四期),寻找乐于分享,精益求精的伙伴
华为开发者联盟HarmonyOS课程体验官(第四期)活动,开始招募啦! 如果你精益求精.乐于分享:如果你愿意为学堂课程优化改进出谋划策,那就快来加入我们吧!学堂期待与你共同成长.一起进步! [活动 ...
- Vue Mixin 的深入浅出
mixin, 意为混入. 比如去买冰激凌,我先要一点奶油的,再来点香草的.我就可以吃一个奶油香草的冰激凌.如果再加点草莓,我可以同时吃三个口味的冰激凌. 代码表示 假设把你已有的奶油味的称为 base ...
- ASP.NET MVC5.0 筑基到炼气大圆满一篇就搞定
一.ASP.NET MVC 过滤器 ASP.NET MVC框架支持四种不同类型的过滤器: 授权过滤器 - 实现IAuthorizationFilter属性. 动作过滤器 - 实现IActionFilt ...
- FFmpeg开发笔记(十六)Linux交叉编译Android的OpenSSL库
<FFmpeg开发实战:从零基础到短视频上线>一书的例程主要测试本地的音视频文件,当然为了安全起见,很多网络视频都采用了https地址.FFmpeg若要访问https视频,就必须集成第三 ...
- 平安保险基于 SPI 机制的 RocketMQ 定制化应用
简介:本文讲讲述平安保险为何选择 RocketMQ,以及在确定使用消息中间件后,又是如何去选择哪款消息中间件的. 作者:孙园园|平安人寿资深开发 为什么选用 RocketMQ 首先跟大家聊聊我们为什 ...
- 十年再出发,Dubbo 3.0 Preview 即将在 3 月发布
简介:随着Dubbo和HSF的整合,我们在整个开源的体系中更多地去展现了 HSF 的能力,能够让更多的人通过使用 Dubbo 像阿里巴巴之前使用 HSF 一样更好的构建服务化的系统. 2011 年, ...
- KubeDL 0.4.0 - Kubernetes AI 模型版本管理与追踪
简介:欢迎更多的用户试用 KubeDL,并向我们提出宝贵的意见,也期待有更多的开发者关注以及参与 KubeDL 社区的建设! 作者:陈裘凯( 求索) 前言 KubeDL 是阿里开源的基于 Kuber ...
- Spring Cloud Gateway一次请求调用源码解析
简介: 最近通过深入学习Spring Cloud Gateway发现这个框架的架构设计非常简单.有效,很多组件的设计都非常值得学习,本文就Spring Cloud Gateway做一个简单的介绍,以及 ...