Java同步与线程安全,同步方法、同步块和java.util.concurrent包的使用

Java的同步与线程安全是并发编程中至关重要的部分。在多线程环境下,确保数据的一致性和避免竞态条件(race condition)是程序设计的关键。

一、Java中的线程安全

线程安全(Thread Safety)是指多线程环境下,多个线程访问同一个对象时,保证对象的状态和行为是正确的。线程安全的主要挑战是避免竞态条件,这种情况发生在多个线程同时访问和修改共享资源时,导致数据不一致或不可预测的行为。

二、同步方法(Synchronized Methods)

1. 什么是同步方法

同步方法是使用synchronized关键字声明的方法。当一个方法被声明为同步方法时,线程必须获得对象的内置锁(intrinsic lock),即监视器锁(monitor lock),才能执行该方法。这意味着同一时间只有一个线程可以执行这个同步方法,其他线程必须等待,直到持有锁的线程释放锁。

2. 同步方法的实现

同步方法的声明很简单,只需在方法前加上synchronized关键字:

public class SynchronizedExample {private int count = 0;public synchronized void increment() {count++;}public synchronized int getCount() {return count;}
}

在上面的例子中,incrementgetCount方法都是同步的。如果一个线程正在执行increment方法,其他线程将无法执行这两个同步方法中的任何一个,直到第一个线程完成increment方法并释放锁。

3. 静态同步方法

静态同步方法使用的是类级别的锁(Class Level Lock),而不是实例级别的锁。其声明方式如下:

public class SynchronizedStaticExample {private static int count = 0;public static synchronized void increment() {count++;}public static synchronized int getCount() {return count;}
}

静态同步方法对于类的所有实例都只有一个锁,因此同一时间只能有一个线程执行这些静态同步方法。

三、同步块(Synchronized Blocks)

1. 什么是同步块

同步块是指在方法内部的一部分代码块前加上synchronized关键字。这种方式允许开发者更细粒度地控制同步范围,进而提高并发性能。

2. 同步块的实现

同步块通常使用对象实例作为锁:

public class SynchronizedBlockExample {private final Object lock = new Object();private int count = 0;public void increment() {synchronized (lock) {count++;}}public int getCount() {synchronized (lock) {return count;}}
}

在上面的例子中,我们创建了一个名为lock的对象,并在synchronized块中使用它来实现同步。这样做的好处是可以仅对需要同步的代码部分加锁,而不是对整个方法加锁,从而提升性能。

3. 使用this作为锁

有时,也可以直接使用this对象作为锁:

public class SynchronizedThisExample {private int count = 0;public void increment() {synchronized (this) {count++;}}public int getCount() {synchronized (this) {return count;}}
}

使用this作为锁的同步块,意味着同步块所包含的代码在执行时必须获得当前实例的锁。

四、java.util.concurrent

java.util.concurrent包提供了一组强大的工具,用于简化并发编程,并提高程序的性能和可维护性。

1. 锁(Locks)

java.util.concurrent.locks包中提供了显式锁(Explicit Lock),如ReentrantLock,其功能比内置锁更加强大和灵活。

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;public class ReentrantLockExample {private final Lock lock = new ReentrantLock();private int count = 0;public void increment() {lock.lock();try {count++;} finally {lock.unlock();}}public int getCount() {lock.lock();try {return count;} finally {lock.unlock();}}
}

使用显式锁时,必须在finally块中释放锁,以确保在任何情况下锁都会被正确释放。

2. 原子变量(Atomic Variables)

java.util.concurrent.atomic包提供了一组原子变量类,如AtomicIntegerAtomicLong等,用于高效地实现线程安全的数值操作。

import java.util.concurrent.atomic.AtomicInteger;public class AtomicExample {private final AtomicInteger count = new AtomicInteger(0);public void increment() {count.incrementAndGet();}public int getCount() {return count.get();}
}

原子变量通过底层的CAS(Compare-And-Swap)操作实现无锁的线程安全,因此在高并发场景下性能更好。

3. 并发集合(Concurrent Collections)

java.util.concurrent包中提供了多个线程安全的集合类,如ConcurrentHashMapCopyOnWriteArrayList等。这些集合类在内部实现了高效的并发控制,避免了传统集合类在多线程环境下的并发问题。

import java.util.concurrent.ConcurrentHashMap;
import java.util.Map;public class ConcurrentHashMapExample {private final Map<String, Integer> map = new ConcurrentHashMap<>();public void put(String key, Integer value) {map.put(key, value);}public Integer get(String key) {return map.get(key);}
}

ConcurrentHashMap通过分段锁(Segmented Locking)实现高并发性能,适用于需要频繁读写操作的场景。

4. 线程池(Thread Pools)

线程池是管理和重用线程资源的重要工具,java.util.concurrent包提供了丰富的线程池实现,如ThreadPoolExecutorScheduledThreadPoolExecutor等。

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class ThreadPoolExample {private final ExecutorService executor = Executors.newFixedThreadPool(10);public void submitTask(Runnable task) {executor.submit(task);}public void shutdown() {executor.shutdown();}
}

线程池通过复用一组线程来执行多个任务,避免了频繁创建和销毁线程的开销,提高了程序的性能和稳定性。

5. 同步辅助类(Synchronizers)

java.util.concurrent包中还提供了多种同步辅助类,如CountDownLatchCyclicBarrierSemaphore等,用于协调线程之间的同步。

CountDownLatch

CountDownLatch是一种同步辅助类,用于让一个或多个线程等待一组操作完成。

import java.util.concurrent.CountDownLatch;public class CountDownLatchExample {private final CountDownLatch latch = new CountDownLatch(3);public void performTask() throws InterruptedException {latch.await();// Perform some action after all tasks are done}public void completeTask() {latch.countDown();}
}
CyclicBarrier

CyclicBarrier是一种用于多个线程相互等待,直到所有线程都到达某个屏障点(Barrier)。

import java.util.concurrent.CyclicBarrier;public class CyclicBarrierExample {private final CyclicBarrier barrier = new CyclicBarrier(3, () -> {// Action to be performed when all threads reach the barrier});public void performTask() throws Exception {barrier.await();// Perform some action after all threads reach the barrier}
}
Semaphore

Semaphore是一种用于控制同时访问某特定资源的线程数量的机制。

import java.util.concurrent.Semaphore;public class SemaphoreExample {private final Semaphore semaphore = new Semaphore(3);public void performTask() throws InterruptedException {semaphore.acquire();try {// Access shared resource} finally {semaphore.release();}}
}

6. Future和Callable

FutureCallable接口用于表示和处理异步计算的结果。

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;public class FutureCallableExample {private final ExecutorService executor = Executors.newFixedThreadPool(10);public void performTask() throws ExecutionException, InterruptedException {Callable<Integer> task = () -> {// Perform some computationreturn 42;};Future<Integer> future = executor.submit(task);Integer result = future.get(); // Blocks until the computation is complete}public void shutdown() {executor.shutdown();}
}

7. ForkJoinPool

ForkJoinPool是专为任务拆分和合并而设计的线程池,适用于递归任务的并行处理。

import java.util.concurrent.RecursiveTask;
import java.util.concurrent.ForkJoinPool;public class ForkJoinExample {static class Fibonacci extends RecursiveTask<Integer> {final int n;Fibonacci(int n) {this.n = n;}@Overrideprotected Integer compute() {if (n <= 1) {return n;}Fibonacci f1 = new Fibonacci(n - 1);f1.fork();Fibonacci f2 = new Fibonacci(n - 2);return f2.compute() + f1.join();}}public static void main(String[] args) {ForkJoinPool pool = new ForkJoinPool();Fibonacci task = new Fibonacci(10);int result = pool.invoke(task);System.out.println("Fibonacci number: " + result);}
}

ForkJoinPool通过工作窃取算法(Work Stealing Algorithm)实现高效的并行计算。

同步方法和同步块是Java内置的同步机制,用于控制对共享资源的访问。而java.util.concurrent包提供了更高级和灵活的并发工具,包括显式锁、原子变量、并发集合、线程池、同步辅助类、Future和Callable以及ForkJoinPool等。这些工具极大地简化了并发编程,提高了程序的性能和稳定性。

黑马程序员免费预约咨询

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/22580.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

一键开启:盲盒小程序里的梦幻奇遇

在繁忙的都市生活中&#xff0c;每个人心中都藏着一个关于奇遇的梦想。如今&#xff0c;我们为您精心打造了一款盲盒小程序——“梦幻奇遇”&#xff0c;只需一键开启&#xff0c;就能带您走进一个充满无限惊喜和梦幻色彩的奇幻世界。 一、神秘盲盒&#xff0c;惊喜连连 “梦幻…

gitlab之cicd的gitlab-runner集成-dockerfile构建环境

目录 概述离线资源docker-compose问题 docker-compose问题1问题2 gitlab-runner集成gitlab 概述 cicd引文目录是想通过dockerfile构建 maven、jdk、docker环境的 gitlab-runner 运行环境。但docker最后测试的时候有点问题&#xff0c;且最后使用 kubectl 时有麻烦&#xff0c;所…

python--面向对象-文件读写-异常

一、继承 定义一个类时&#xff0c;需要使用另外一个类的方法或属性&#xff0c;就可以通过继承实现 object是Python的顶级类&#xff0c;创建类是会自动继承&#xff0c;就拥有object中的方法 定义格式 # 类的定义 # 旧式类定义 一般在定义单个类时使用 class 类名:name N…

Spring Boot 使用自定义注解和自定义线程池实现异步日志记录

&#x1f604; 19年之后由于某些原因断更了三年&#xff0c;23年重新扬帆起航&#xff0c;推出更多优质博文&#xff0c;希望大家多多支持&#xff5e; &#x1f337; 古之立大事者&#xff0c;不惟有超世之才&#xff0c;亦必有坚忍不拔之志 &#x1f390; 个人CSND主页——Mi…

如何保持气膜场馆内部空气新鲜—轻空间

气膜建筑作为现代建筑的一种新兴形式&#xff0c;以其独特的优势和设计受到了广泛欢迎。然而&#xff0c;保持气膜内部空气新鲜是一个必须解决的问题。我们通过配备先进的新风系统&#xff0c;提供了高效的解决方案。 新风系统的工作原理 气膜建筑内部空气的新鲜度主要依靠其配…

【vscode-快捷键 一键JSON格式化】

网上有很多JSON格式化工具&#xff0c;也有很多好用的在线json格式化工具。但是其实Vscode里面的可以直接格式化JSON&#xff0c;这里分享一个我常用的小插件 Prettify JSON 未格式化的JSON数据 召唤出命令行&#xff0c;输入prettify JSON 即可! ✿✿ヽ(▽)ノ✿

算法题:Java求数组中最大的值

采用分而治之&#xff08;二分法&#xff09;的思想去求解 分而治之&#xff1a;分而治之的思想可以用于解决很多问题&#xff0c;大概的思路就是把一个比较大的复杂的问题切分成小的块&#xff0c;然后分头去解决他们&#xff0c;最后再把结果合并起来&#xff0c;就是“分而治…

快速理解 Node.js 版本差异:3 分钟指南

Node.js 是一个广泛使用的 JavaScript 运行时环境&#xff0c;允许开发者在服务器端运行 JavaScript 代码。随着技术的发展&#xff0c;Node.js 不断推出新版本&#xff0c;引入新特性和改进。了解不同版本之间的差异对于开发者来说至关重要。以下是一个快速指南&#xff0c;帮…

C++高级 - 接口模板

目录 一. 接口 二. 模板 一. 接口 接口通常是通过抽象类或纯虚函数来实现的。 以下是一个使用抽象类来定义接口的示例代码&#xff1a; #include <iostream>class Interface { public:virtual void operation() 0; // 纯虚函数定义接口 };class ConcreteClass : pu…

【图书推荐】《Ubuntu Linux系统管理与运维实战》

本书重点 全面学习Ubuntu系统操作&#xff0c;快速掌握Linux日常管理和运维 安装和配置、桌面环境、文件系统、文件和目录管理、用户和权限管理系统的启动和关闭、服务和进程管理、软件包管理、磁盘和文件系统管理网络管理、网络服务管理、系统和网络安全 内容简介 Linux是…

计算机基础(5)——进制与进制转换

&#x1f497;计算机基础系列文章&#x1f497; &#x1f449;&#x1f340;计算机基础&#xff08;1&#xff09;——计算机的发展史&#x1f340;&#x1f449;&#x1f340;计算机基础&#xff08;2&#xff09;——冯诺依曼体系结构&#x1f340;&#x1f449;&#x1f34…

了解一下Ubuntu Linux

1.3.1 什么是Ubuntu Ubuntu这个名字非常神奇&#xff0c;它取自非洲南部祖鲁语的ubuntu&#xff0c;是一个哲学名称&#xff0c;其意思为“人性”或者“我的存在是因为大家的存在”。对于中国人来说&#xff0c;一般称呼它为乌班图。 Ubuntu是在Debian的基础上开发出来的&am…

opencv标定板图像位置

下载的C中使用的opencv库有圆点和方格的标定板图像 Opencv4.6.0\sources\doc

什么是泛洪攻击?DDos攻击也是泛洪攻击的一种?

在数字化时代的浪潮中&#xff0c;网络安全已成为一场没有硝烟的战争。其中&#xff0c;泛洪攻击作为一种常见的网络攻击手段&#xff0c;对个人用户、企业乃至国家网络安全构成了严重威胁。本文将对泛洪攻击进行深入剖析&#xff0c;包括其定义、原理、类型、影响以及应对策略…

嵌入式Linux系统编程 — 1.4 原子操作与竞争冒险

目录 1 竞争冒险 1.1 竞争冒险由来 1.2 竞争冒险理解 2 原子操作 2.1 O_APPEND 实现原子操作 2.2 pread()和 pwrite() 2.3 O_EXCL 标志创建文件 1 竞争冒险 1.1 竞争冒险由来 Linux 是一个支持多任务和多用户同时运行的操作系统&#xff0c;它允许多个进程同时执行。…

kube-promethesu新增k8s组件监控(etcd\kube-controller-manage\kube-scheduler)

我们的k8s集群是二进制部署 一、prometheus添加自定义监控与告警&#xff08;etcd&#xff09; 1、步骤及注意事项&#xff08;前提&#xff0c;部署参考部署篇&#xff09; 1.1 一般etcd集群会开启HTTPS认证&#xff0c;因此访问etcd需要对应的证书 1.2 使用证书创建etcd的…

Verilog实战学习到RiscV - 3 : ICEStick 评估板点灯

收到 ICESTICK 评估板后还没好好玩。先来点个灯&#xff0c;正好把之前介绍过的工具链串起来用一下。 代码 Verilog代码只有一个顶层模块top.v&#xff0c;定义如下&#xff1a; module top(output wire D1,output wire D2,output wire D3,output wire D4,output wire D5);a…

云手机定位切换,带来的不只是便利

当我们利用云手机的定位切换时&#xff0c;首先感受到的确实是极大的便利。 我们就像是拥有了瞬间移动的超能力&#xff0c;可以自由地在不同城市、甚至不同国家的虚拟场景中穿梭。无论是为了更精准地获取当地的信息&#xff0c;比如实时的交通状况、特色店铺等&#xff0c;还…

【CT】LeetCode手撕—3. 无重复字符的最长子串

目录 题目1- 思路1-1 模式1&#xff1a;涉及去重判断1-2 模式2&#xff1a;遍历字符串区间 2- 题解⭐无重复字符的最长子串——题解思路 3- ACM实现 原题链接&#xff1a;3. 无重复字符的最长子串 题目 无重复字符的最长子串 给定一个字符串 s &#xff0c;请你找出其中不含有…

裸芯片绑定键合电阻器

EAK厚膜阻芯与有源裸片键合在一起封装 一般说明 精密引线键合电阻具有极高的稳定性和可靠性。电阻器经过激光微调&#xff0c;达到严格的公差。可定制值和该值的唯一标记&#xff0c;非常适合但不限于混合电路应用。 潜在作用&#xff1a; 医用植入式 军事/国防 混合设计 …