当前位置: 首页 > news >正文

多线程基础知识-

线程同步需要注意什么

       ,线程同步是一种机制,用于确保多个线程在访问共享资源时的安全性。在进行线程同步时,需要注意以下几点:

  1. 互斥性:确保同一时间只有一个线程可以访问共享资源。可以使用synchronized关键字来实现互斥锁。

  2. 可见性:确保一个线程对共享变量的修改对其他线程可见。可以使用volatile关键字来实现可见性。

  3. 有序性:确保线程按照一定的顺序执行共享资源的操作。可以使用synchronized关键字或者Lock接口的相关方法来实现有序性。

  4. 线程安全性:确保多个线程同时访问共享资源时,不会出现数据的不一致或者错误。可以使用同步块或者同步方法来保证线程安全性。

  5. 死锁:避免在多个线程之间形成循环等待资源的局面,导致线程无法继续执行。可以使用避免死锁的算法和机制来解决死锁问题。

需要注意的是,虽然线程同步可以确保共享资源的安全性,但是过度使用线程同步可能会导致性能问题或者死锁问题。

线程 wait()方法使用有什么前提

     在Java中,线程的wait()方法用于将一个线程设置为等待状态,直到其他线程调用了notify()或notifyAll()方法来唤醒它。为了正确使用wait()方法,需要满足以下前提条件:

  1. wait()方法必须在synchronized代码块或synchronized方法中调用。这是因为wait()方法会释放当前线程持有的锁,并进入等待状态,等待其他线程调用notify()或notifyAll()方法来唤醒它。如果没有在synchronized代码块或synchronized方法中调用wait()方法,会抛出IllegalMonitorStateException异常。

  2. wait()方法必须在循环中调用。由于线程可能在被唤醒后重新进入竞争状态,因此在wait()方法调用后,应该在循环中重新检查等待条件。

  3. wait()方法应该始终与条件判断一起使用。在调用wait()方法前,应该先判断等待条件是否满足,如果不满足则继续等待,直到条件满足后再调用wait()方法。

使用wait()方法的前提条件是在synchronized代码块或synchronized方法中调用,并且在循环中检查等待条件。这样可以保证线程在等待和被唤醒时的正确行为。

线程之间如何传递数据

     

在Java中,线程之间可以通过共享的变量来传递数据。可以使用以下几种方式来实现线程之间的数据传递:

  1. 使用共享变量:多个线程共享一个变量,可以通过对该变量的读写操作进行数据传递。
class MyThread extends Thread {private int shareData;public void run() {// 线程逻辑代码// 通过对shareData进行读写操作传递数据shareData = 10;}
}public class Main {public static void main(String[] args) {MyThread thread = new MyThread();thread.start();// 等待线程执行完毕thread.join();// 获取线程传递的数据int data = thread.shareData;System.out.println(data);}
}

  1. 使用共享对象:多个线程共享同一个对象,可以通过该对象的方法来进行数据传递。
class SharedObject {private int data;public synchronized void setData(int data) {this.data = data;}public synchronized int getData() {return data;}
}class MyThread extends Thread {private SharedObject sharedObject;public MyThread(SharedObject sharedObject) {this.sharedObject = sharedObject;}public void run() {// 线程逻辑代码// 通过调用共享对象的方法进行数据传递sharedObject.setData(10);}
}public class Main {public static void main(String[] args) {SharedObject sharedObject = new SharedObject();MyThread thread = new MyThread(sharedObject);thread.start();// 等待线程执行完毕thread.join();// 获取线程传递的数据int data = sharedObject.getData();System.out.println(data);}
}

  1. 使用线程池和Future对象:线程池可以提交任务并返回一个Future对象,通过该对象可以获取任务的执行结果。
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;class MyCallable implements Callable<Integer> {public Integer call() {// 任务逻辑代码return 10;}
}public class Main {public static void main(String[] args) throws ExecutionException, InterruptedException {ExecutorService executorService = Executors.newFixedThreadPool(1);Future<Integer> future = executorService.submit(new MyCallable());// 等待任务执行完毕并获取结果int data = future.get();System.out.println(data);executorService.shutdown();}
}

几个常用的 Lock 接口实现锁

      

Java中常用的Lock接口的实现类有以下几个:

  1. ReentrantLock:可重入锁,是Lock接口的主要实现类之一。它提供了与synchronized关键字类似的功能,但更加灵活和可扩展。
  2. ReadWriteLock:读写锁,也是Lock接口的实现类之一。它允许多个线程同时读取数据,但只允许一个线程写入数据。
  3. ReentrantReadWriteLock:可重入读写锁,是ReadWriteLock接口的实现类。它提供了可重入的读写锁功能,允许多个线程同时读取数据,但只允许一个线程写入数据。

以下是各个锁的代码示例:

  1. ReentrantLock:
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;public class ReentrantLockExample {private Lock lock = new ReentrantLock();public void doSomething() {lock.lock();try {// 临界区代码} finally {lock.unlock();}}
}

  1. ReadWriteLock:
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;public class ReadWriteLockExample {private ReadWriteLock lock = new ReentrantReadWriteLock();public void readData() {lock.readLock().lock();try {// 读取数据} finally {lock.readLock().unlock();}}public void writeData() {lock.writeLock().lock();try {// 写入数据} finally {lock.writeLock().unlock();}}
}

  1. ReentrantReadWriteLock:
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;public class ReentrantReadWriteLockExample {private ReadWriteLock lock = new ReentrantReadWriteLock();public void readData() {lock.readLock().lock();try {// 读取数据} finally {lock.readLock().unlock();}}public void writeData() {lock.writeLock().lock();try {// 写入数据} finally {lock.writeLock().unlock();}}
}

总结 

     

多线程中的wait()方法是Object类中的方法,用于线程间的通信,它会使当前线程进入等待状态,直到其他线程调用notify()或者notifyAll()方法将其唤醒。

wait()方法的总结如下:

  1. wait()方法必须在同步方法或同步代码块中被调用,否则会抛出IllegalMonitorStateException异常。

  2. 在调用wait()方法后,线程会释放锁,进入等待状态,直到其他线程通过notify()或者notifyAll()方法唤醒它。

  3. 被唤醒的线程会重新竞争锁,一旦获得锁,就会从wait()方法返回继续执行。

  4. wait()方法可以被中断,如果线程在等待过程中被中断,会抛出InterruptedException异常。

  5. wait()方法还可以使用带有超时时间的版本,例如wait(long timeout),表示等待一定的时间后自动唤醒。

  6. wait()方法应该始终在循环中使用,以防止虚假唤醒。

  7. wait()方法的使用场景可以是线程间的协作,例如生产者-消费者模式,一个线程负责生产数据,另一个线程负责消费数据,当生产者线程没有数据可供消费时,调用wait()方法等待消费者线程的唤醒。

    

相关文章:

  • 游戏逆向工具分析及解决方案
  • Charles-ios无法抓包原因之一证书
  • 反射获取成员变量
  • 单片机按键处理模块
  • PostgreSQL的学习心得和知识总结(一百四十四)|深入理解PostgreSQL数据库之sendTuples的实现原理及功能修改
  • JZ2440笔记:rtc驱动
  • 修改wsl2默认配置使宿主机不能使用localhost或127.0.0.1访问WSL
  • 32. 【Java教程】集合
  • rtl8723DU移植 android4.4 4418
  • Go基础编程 - 03 - init函数、main函数、_(下划线)
  • 练习题-17
  • Spring IoC 的实现机制
  • Linux用户权限管理小实验002
  • C++牛客周赛43题目分享(3)小红平分糖果,小红的完全平方数,小苯的字符串变化,小红的子数组排列判断
  • 【云原生】kubernetes中的认证、权限设置--RBAC授权原理分析与应用实战
  • 【刷算法】求1+2+3+...+n
  • 5分钟即可掌握的前端高效利器:JavaScript 策略模式
  • android高仿小视频、应用锁、3种存储库、QQ小红点动画、仿支付宝图表等源码...
  • CAP 一致性协议及应用解析
  • Druid 在有赞的实践
  • js学习笔记
  • js中forEach回调同异步问题
  • SegmentFault 社区上线小程序开发频道,助力小程序开发者生态
  • Vue UI框架库开发介绍
  • 阿里云ubuntu14.04 Nginx反向代理Nodejs
  • 从地狱到天堂,Node 回调向 async/await 转变
  • 给新手的新浪微博 SDK 集成教程【一】
  • 工程优化暨babel升级小记
  • 关于List、List?、ListObject的区别
  • 观察者模式实现非直接耦合
  • 通过npm或yarn自动生成vue组件
  • mysql 慢查询分析工具:pt-query-digest 在mac 上的安装使用 ...
  • # centos7下FFmpeg环境部署记录
  • ###51单片机学习(2)-----如何通过C语言运用延时函数设计LED流水灯
  • #Linux杂记--将Python3的源码编译为.so文件方法与Linux环境下的交叉编译方法
  • (23)Linux的软硬连接
  • (C语言)深入理解指针2之野指针与传值与传址与assert断言
  • (delphi11最新学习资料) Object Pascal 学习笔记---第14章泛型第2节(泛型类的类构造函数)
  • (ibm)Java 语言的 XPath API
  • (安全基本功)磁盘MBR,分区表,活动分区,引导扇区。。。详解与区别
  • (三)centos7案例实战—vmware虚拟机硬盘挂载与卸载
  • (生成器)yield与(迭代器)generator
  • (使用vite搭建vue3项目(vite + vue3 + vue router + pinia + element plus))
  • .gitignore文件---让git自动忽略指定文件
  • .md即markdown文件的基本常用编写语法
  • .net core 调用c dll_用C++生成一个简单的DLL文件VS2008
  • .NET Core使用NPOI导出复杂,美观的Excel详解
  • .net on S60 ---- Net60 1.1发布 支持VS2008以及新的特性
  • .Net 访问电子邮箱-LumiSoft.Net,好用
  • .net 重复调用webservice_Java RMI 远程调用详解,优劣势说明
  • .net中的Queue和Stack
  • @EnableAsync和@Async开始异步任务支持
  • @Responsebody与@RequestBody
  • [2013][note]通过石墨烯调谐用于开关、传感的动态可重构Fano超——
  • [2024-06]-[大模型]-[Ollama]- WebUI