线程的同步
线程的特点
计算机中一个程序可以启动多个进程,一个进程又可以启动多个线程。进程之间在内存中是相互独立的,它们不能彼此进行访问,已不能修改彼此的数据,那么进程之间怎样做到共享数据呢,一般有两种方法,第一种是通过网络,即进程A把数据发到服务器,然后服务器再将这些数据发给进程B,同样进程B也可以把数据发到服务器,然后服务器再将这些数据发给进程A;第二种方式是进程A把数据存到本地的硬盘文件中,然后进程B再到硬盘里去读这个文件,同样进程B也可以把数据存到本地的硬盘文件中,然后进程A再到硬盘里去读这个文件。但是,进程启动的多个线程中间是可以共享内存里的数据的,也可以修改这些数据。还有进程之间可以并发执行,即同步执行。
线程同步的好处
当一个计算很复杂或是很庞大的时候,我们可以把它分为若干个比较简单的计算模块,然后再把这若干个计算模块交给若干个线程去处理,最后把这些返回的计算结果统计整理。比如我们有统计计算机中所有文件的个数。我们就可以启动多个线程去统计每一个盘符里面的文件个数,然后再把它们全部加起来,就可以得到文件的总个数。
其代码如下:
public class Filecount extends Thread{ private int num;//用来保存文件个数的属性 private String name;//文件的路径 private boolean bl=false;//用来判断文件是否统计完的一个属性 /** * 重载构造方法,得到要统计的文件名 */ public Filecount(String name){ this.name=name; } //获得统计后的文件个数 public int getNum(){ return num; } //一个或得统计状态的方法,true代表已经统计完了,false代表没有统计完 public boolean isFinish(){ return bl; } //重写线程的run方法 public void run(){ count(name); bl=true; } /** * 统计文件的方法 */ public void count(String name){ // 根据文件路径创建文件对象 java.io.File file=new java.io.File(name); // 如果表示的文件不存在 if(!file.exists()){ return; } // 将该文件夹下的所有文件装在一个文件数组中 java.io.File[] myfs=file.listFiles(); if(myfs==null){ return; } // 遍历数组 for(int i=0;i<myfs.length;i++){ java.io.File fs=myfs[i]; // 得到文件的地址 String s=fs.getAbsolutePath(); // 如果是一个标准文件 if(fs.isFile()){ //文件加一 num++; //如果是文件夹 }else if(fs.isDirectory()){ //递归调用 try{//进行适当的休眠以免cpu被过度占用 Thread.sleep(20); }catch(Exception ef){ ef.printStackTrace(); } this.count(s); } } } }
测试的主函数
public class Counter extends Thread{ private int filenum=0;//用来保存文件个数 public static void main(String[] args) { Counter count=new Counter();//创建一个统计所有文件个数的对象 count.start(); //启动线程去统计所有线程返回的结果 } //重载run方法 public void run(){ Filecount E_counter=new Filecount("E:\\");//创建一个统计E盘的对象 E_counter.start(); Filecount F_counter=new Filecount("F:\\");//创建一个统计F盘的对象 F_counter.start(); while(true){ if(E_counter.isFinish()&&F_counter.isFinish()){//不断的判断线程是否已经把所有文件统计完了 break;//跳出循环 } try{//进行适当的休眠 Thread.sleep(200); }catch(Exception ex){ ex.printStackTrace(); } } filenum=E_counter.getNum()+F_counter.getNum(); System.out.println("标准文件的总个数为:"+filenum); } }
如果要进一步的提过效率,我们可以通过对文件进行判断,若是一个很大的文件,我们可以在启动线程去统计。
通过将任务进行分配,有时是可以提过效率,但是并不是把任务分配给线程,就一定能提过效率。像上面统计文件个数的情况,如果我只是简单的分配任务,其实并不能提高效率。而且像上面的情况是,线程什么时候运行结束了,并不知道。所以我们得优化线程的工作机制。
同步线程的影响
假设一下,如果有两个线程同时对一个变量进行操作,会有什么情况。因为同步线程之间的执行并不是同时的,也不一定是按照先后的顺序执行的,这取决与CPU和操作系统等因素。所以当两个或以上的线程同时操作同一块内存时,就有可能会产生影响。这种影响可能会导致一些不可预见的结果。
线程模型的优化
生产/消费者模型的应用,在统计每个盘的文件的时候,因为我们不知道哪个盘的统计已经完成了,所以我们得不停的去询问,也就是不断的去判断它们是否已经全部统计完了,这样做显然很不合理,那么我们能不能改进一下呢,当然是可以的。看到生产和消费是不是有些不理解,凭常识我们就能知道必须先生产出东西来,我才能进行消费,所以只要当我们知道生产这把东西生产出来就可以去买了。在“产品”
没有生产出来之前,我们就必须得在家里等到,知道有人通知我们产品已经生产出来了,我们才去买。这样在中生产/消费者模型有别转会成为等待/通知(wait()/notify())模型了。
下面是实现这种机制的具体代码
public class Filecount extends Thread{ private int num;//用来保存文件个数的属性 private String name;//文件的路径 private Counter count; /** * 重载构造方法,得到要统计的文件名 */ public Filecount(String name,Counter count){ this.name=name; this.count=count; } //获得统计后的文件个数 public int getNum(){ return num; } //重写线程的run方法 public void run(){ count(name);//统计文件个数的方法 synchronized(count){//将counter对象锁住 count.notify();// 统计完该盘的文件个数后,就通知它 } } /** * 统计文件的方法 */ public void count(String name){//统计文件个数的方法 public void count(String name){ // 根据文件路径创建文件对象 java.io.File file=new java.io.File(name); // 如果表示的文件不存在 if(!file.exists()){ return; } // 将该文件夹下的所有文件装在一个文件数组中 java.io.File[] myfs=file.listFiles(); if(myfs==null){ return; } // 遍历数组 for(int i=0;i<myfs.length;i++){ java.io.File fs=myfs[i]; // 得到文件的地址 String s=fs.getAbsolutePath(); // 如果是一个标准文件 if(fs.isFile()){ //文件加一 num++; //如果是文件夹 }else if(fs.isDirectory()){ //递归调用 try{//进行适当的休眠以免cpu被过度占用 Thread.sleep(20); }catch(Exception ef){ ef.printStackTrace(); } this.count(s); } } }}
public class Counter extends Thread{ private int filenum=0;//用来保存文件个数 public static void main(String[] args) { Counter count=new Counter();//创建一个统计所有文件个数的对象 count.start(); //启动线程去统计所有线程返回的结果 } //重载run方法 public void run(){ Filecount E_counter=new Filecount("E:\\",this);//创建一个统计E盘的对象 E_counter.start(); Filecount F_counter=new Filecount("F:\\",this);//创建一个统计F盘的对象 F_counter.start(); synchronized(this){//将当前这个对象锁住 try { this.wait();//等待通知第一个统计者的通知 this.wait();//等待通知第二个统计者的通知 } catch (InterruptedException e) { e.printStackTrace(); } } filenum=E_counter.getNum()+F_counter.getNum(); System.out.println("标准文件的总个数为:"+filenum); } }
里面使用的wait()有阻塞的作用,用就是说如果等不到通知notify(),wait()就不会执行下去,就可阻塞在wait()里。
相关推荐
在VC++编程环境中,线程同步是一个至关重要的概念,特别是在多线程程序设计中,以确保并发执行的线程能够安全地访问共享资源,避免数据竞争和其他潜在的问题。本篇文章将详细探讨线程锁在VC++中的应用,以及如何通过...
线程同步是多线程编程中的重要概念,用于协调多个并发执行的线程,确保它们在访问共享资源时不会产生竞态条件或数据不一致性。在Windows编程中,提供了多种线程同步机制,包括互斥量、临界区、原子操作、事件以及...
操作系统线程同步是多线程编程中的核心概念,旨在确保并发执行的线程在访问共享资源时不会引发数据不一致性和竞态条件。本实验报告详细探讨了这一主题,通过一个简单的银行账户转账的示例来揭示临界区问题及其解决...
在多线程编程中,线程同步是一种控制多个线程并发执行时访问共享资源的方式,以避免数据不一致和死锁等问题。以下是对线程同步的四种主要方式的详细解释: 1. **事件(Event)** 事件是Windows API提供的一种线程...
在这个“线程同步解决火车站售票问题”的例子中,我们可以通过线程同步机制来实现售票的有序、无冲突的过程。 首先,我们需要理解问题的核心:10个售票处(线程)需要共享1000张票(资源),并且每卖出一张票,必须...
操作系统中的多线程同步是一个关键概念,特别是在并发编程中,它涉及到如何协调多个线程以避免数据不一致性和竞态条件。在这个实验中,我们关注的是C++编程语言中的实现,以及操作系统如何处理线程的优先级。 首先...
本示例“简单实现多线程同步示例(模拟购票系统)”旨在通过一个具体的实例,帮助开发者理解如何在Java中创建并管理多线程以及如何实现线程同步,确保数据的一致性和正确性。 首先,我们要明确多线程的基本概念。在...
在编程领域,线程同步是多线程编程中的一个重要概念,它确保了多个线程在访问共享资源时的正确性和一致性。在这个“VC++线程同步实例”中,我们将探讨如何利用VC++(Visual C++)来实现线程间的同步,以避免数据竞争...
操作系统中的线程同步是多线程编程中一个关键的概念,它确保了多个线程在访问共享资源时的正确性,防止数据竞争和其他并发问题。在Windows操作系统中,提供了多种线程同步机制,如临界区、事件、信号量以及互斥量等...
本文将深入探讨Delphi中的多线程和线程同步,并以"SortThreads"和"delphi-thread-gui"这两个示例项目为例,讲解如何在实践中应用这些概念。 1. **多线程**:多线程允许应用程序同时执行多个独立的任务,提高程序的...
然而,多线程环境下也带来了一些问题,尤其是资源竞争和数据一致性问题,这些问题需要通过线程同步机制来解决。本文将详细介绍如何通过临界区、互斥内核对象、事件内核对象和信号量内核对象来实现线程同步。 1. ...
"Java多线程同步.pdf" Java多线程同步是指在Java语言中,如何使用synchronized关键字和其他同步机制来确保多线程程序的正确执行。在Java语言中,synchronized关键字用于对方法或者代码块进行同步,但是仅仅使用...
在编程领域,线程同步是多线程编程中的一个核心概念,它涉及到如何有效地管理和协调多个并发执行的线程,确保它们能正确地共享资源,避免数据竞争和死锁等问题。这个“线程同步小例子”是基于孙鑫先生著作中的示例...
操作系统实验是计算机科学教育中的重要组成部分,它帮助学生理解和掌握操作系统的基本原理,特别是多线程同步与互斥的概念。在Java编程环境下,这些概念可以通过实际的代码实现来深入理解。 多线程是现代操作系统中...
"多线程的批量线程同步解决方案"这个标题暗示我们探讨的是如何在多线程环境下有效地管理和同步多个任务,确保数据一致性与程序正确性。下面将详细阐述相关知识点。 一、多线程基础 多线程是指在一个进程中同时执行...
在本例“Jni多线程同步事例”中,我们将探讨如何在JNI层面上实现多线程同步,特别是在一个生产者-消费者模型的场景下。 生产者-消费者模型是一种经典的并发问题,它涉及到两个或多个线程之间的协作。在该模型中,...
C#线程同步是多线程编程中的一个重要概念,它涉及到如何控制多个线程对共享资源的访问,以避免数据不一致性和竞态条件。在C#中,线程同步通常用于确保在某一时刻只有一个线程可以访问特定的代码块或资源,从而保证...