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,一经查实,立即删除!

相关文章

C++中的注释作用

程序的注释是解释性语句&#xff0c;您可以在 C 代码中包含注释&#xff0c;这将提高源代码的可读性。所有的编程语言都允许某种形式的注释。 C 支持单行注释和多行注释。注释中的所有字符会被 C 编译器忽略。 C 注释一般有两种&#xff1a; // - 一般用于单行注释。 / ...…

【耗时八个小时】机器学习过拟合和欠拟合!看这一篇文章就够了

.. 纯. .干 货 . . . . 在机器学习中&#xff0c;有一项非常重要的概念&#xff0c;那就是&#xff1a;过拟合&#xff08;Overfitting&#xff09;和欠拟合&#xff08;Underfitting&#xff09;。 它们涉及到机器学习中常见的两种模型性能问题&#xff0c;分别表示模型在训练…

[modern c++] 使用shared_mutex , shared_lock完成读写锁,Need C++ 17

前言&#xff1a; C 17开始&#xff0c;引入了两个新的同步组件&#xff0c; shared_mutex 和 shared_lock &#xff0c;这两个组件的一个典型使用案例就是实现读写锁。 原语&#xff1a; shared_mutex &#xff0c; 一个提供让多个线程都可以同时获取能力的mutex。 shared_…

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

在繁忙的都市生活中&#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…

.NET集成DeveloperSharp操作SqlServer、MySql等数据库

&#x1f3c6;作者&#xff1a;科技、互联网行业优质创作者 &#x1f3c6;专注领域&#xff1a;.Net技术、软件架构、人工智能、数字化转型、DeveloperSharp、微服务、工业互联网、智能制造 &#x1f3c6;欢迎关注我&#xff08;Net数字智慧化基地&#xff09;&#xff0c;里面…

在Linux系统中程序是如何执行的?

在Linux系统中&#xff0c;程序的执行是一个复杂而精细的过程&#xff0c;涉及多个步骤。 1.进程创建 在Linux中&#xff0c;进程的创建&#xff0c;除了第一个进程&#xff08;0号进程&#xff09;是通过硬编码创建&#xff0c;其他所有进程通常都是通过fork()系统调用来实现…

力扣2134.最少交换次数得到连续的1(断环成链)

力扣2134.最少交换次数得到连续的1(断环成链) 最终一定是所有1的个数(长度) 的区间 所以求所有1的和 用和作为k作滑动窗口将环断成长度为nsum-1的链 class Solution {public:int minSwaps(vector<int>& nums) {int sum accumulate(nums.begin(),nums.end(),0);in…

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

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

在C++中,NULL和nullptr有什么区别?

在C11之前&#xff0c;一般使用NULL代表空指针。 NULL的定义在C和C中不同&#xff0c;而且C和C针对0和指针之间的运算规则也存在差异&#xff1a; C03标准&#xff1a;空指针常量是整数类型的整型常量表达式右值&#xff0c;其值为零。空指针常量可以转换为指针类型&#xff…

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

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

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

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

C++中的string类详解

在C中&#xff0c;字符串是一个非常重要的数据类型&#xff0c;用于存储和处理文本数据。C标准库提供了std::string类&#xff0c;它是一个模板类&#xff0c;专门用于处理字符串。std::string类提供了丰富的成员函数和操作符重载&#xff0c;使得字符串操作变得简单而高效。本…

【JAVA】把结果保留两位小数的方法

在Java中&#xff0c;保留两位小数可以使用几种不同的方法&#xff0c;下面将详细解释并给出每种方法的例子&#xff1a; 1.使用DecimalFormat类 DecimalFormat是java.text包中的一个类&#xff0c;专门用于格式化数字&#xff0c;包括保留小数点后指定的位数。下面是使用Dec…

git介绍、安装、配置

文章目录 1. GIT介绍2. 使用GIT的好处3. GIT 安装4. GIT 配置4.1 GIT 初始化设置、命令别名设置4.2 如果终端安装了oh-my-zsh&#xff0c;会带一堆git命令别名4.3 GIT配置文件介绍4.3.1 Linux、Mac OS系统4.3.2 windows系统 5. git设置远程仓库账号密码(拉取、上传代码不用输入…

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

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

Unity3D DOTS 10W GPU Intancing 动画与合批优化详解

前言 Unity3D DOTS&#xff08;Data-Oriented Technology Stack&#xff09;是Unity引擎的一个新的技本堆栈&#xff0c;旨在提高游戏的性能和效率。其中的GPU Instancing和合批技术是其重要的优化手段之一。本文将详细介绍Unity3D DOTS中的10W GPU Instancing技术以及动画与合…

高清多媒体接口(High Definition Multimedia Interface, HDMI)

目录 1. Overview1.1. TMDS(Time Minimized Differential Signal)1.2. Display Data Channel(DDC)1.3. CEC1.4. HEAC1.5. HPD2. Signaling and Encoding3. Video4. Control and Configuration5. Compatibility with DVI6. EDID and E-EDID7. HDCP<