Java多线程[3]:线程同步(互斥)
来源:互联网 发布:仿商城html5源码 编辑:程序博客网 时间:2024/04/29 17:25
由于Java中的多线程写起来比较长,为了使博客读起来更加简洁,我决定将java多线程部分拆分开来写。本篇是第三篇,线程同步,也成为线程互斥。
什么是线程同步
当两个或多个线程需要访问共享资源时,它们需要以某种方式确保每次只有一个线程使用资源,实现这一目的的过程称为线程同步。Java为线程同步提供了很好的支持。
监视器的概念常用来解决线程同步问题。监视器是用做互斥锁的对象。在任何时刻,只有一个线程可以拥有监视器。当线程取得锁时,也就进入了监视器。其它所有企图进入加锁监视器的线程都会被挂起,直到第一个线程退出监视器。
在Java中,可以使用两种方法来实现线程之间的同步,这两种方法都会用到synchronized关键字。
- 同步方法
- 同步语句块
不使用线程同步导致的问题
首先我们先给出一个应该使用线程同步而没有使用的应用场景。
首先,我们定义一个工具类叫PrintUtil,用来实现打印输出的功能
public class PrintUtil { public static void Print(String content) { System.out.print("[" + content); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("]"); }}
然后定义一个类NewThread,实现Runnable接口,这个类在run方法中调用了PrintUtil.Print()方法。
public class NewThread implements Runnable { Thread t; String message; public NewThread(String msg) { this.message = msg; t = new Thread(this, "my test thread"); t.start(); } @Override public void run() { PrintUtil.Print(message); }}
下面是main方法。
public class Program { public static void main(String[] args) { NewThread obj1= new NewThread("hello"); NewThread obj2= new NewThread("java"); NewThread obj3= new NewThread("servlet"); try { obj1.t.join(); obj2.t.join(); obj3.t.join(); } catch (InterruptedException e) { e.printStackTrace(); } }}
在main方法中,实例化了三个NewThread对象,也就启动了三个线程,每个线程的run方法都调用了PrintUtil.Print() 方法。由于没有做线程同步的处理,输出的结果如下:
[hello[java[servlet]]]
很明显,这不是我们想要的结果
使用同步方法来实现线程同步
我们必须要限制每次只能由一个线程的run方法来调用Print()方法,并且当该方法执行完毕之后下一个线程才能调用。在Java中,想做到这个是非常容易的,只需要在PrintUtil.Print() 方法前面加上一个关键字synchronized就能轻松搞定。修改后的PrintUtil类的代码如下
public class PrintUtil { synchronized public static void Print(String content) { System.out.print("[" + content); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("]"); }}
其它的地方无需修改。重新运行程序,结果如下:
[hello][servlet][java]
输出的顺序可能会不一样,但左右括号都是完整的。
使用同步语句块来实现线程同步
虽然在类中创建synchronized方法是一种比较容易并且行之有效的实现线程同步的方法,但是,它并不能适用于所有场景。例如:假设PrintUtil类不是由你设计的,你也不能修改它,肿么办?同步语句块诞生了!
首先,我们将PrintUtil.Print() 方法前面的synchronized关键字去掉,然后假装我们没有权限修改这个类。然后,我们来修改NewThread的run方法,修改后的NewThread类的代码如下
public class NewThread implements Runnable { Thread t; String message; //这个对象其实没有卵用,只是为了对它进行加锁,因为这个对象对于多个线程来说是同一个引用 static Object obj = new Object(); public NewThread(String msg) { this.message = msg; t = new Thread(this, "my test thread"); t.start(); } @Override public void run() { synchronized (obj) { PrintUtil.Print(message); } }}
重新运行代码,输出的结果是
[hello][servlet][java]
下面说一下synchronized关键字后面的括号中的对象。这个对象对于多个线程来说,必须是同一个引用,通常情况下是类外部的一个对象。如果在类内部的话,必须声明为静态的。总之,它不能属于当前线程对象,要么属于外部,要么属于当前类(静态)。
- Java多线程[3]:线程同步(互斥)
- Java多线程基础(并发、线程安全、同步、互斥)
- Java多线程编程--(3)线程互斥、同步的理解
- Java多线程编程--(3)线程互斥、同步的理解
- Java多线程编程--(3)线程互斥、同步的理解
- Windows多线程总结(3)-- 线程同步(使用互斥对象实现线程同步)
- 多线程编程 线程互斥 线程同步
- java多线程Thread线程同步与互斥、锁机制
- java多线程:3、线程互斥
- java基础——多线程(线程的同步互斥与通信)
- java基础——多线程(线程的同步互斥与通信)
- 多线程学习3-线程互斥与同步通信
- 多线程——线程同步互斥(synchronized)
- linux多线程-操作系统线程同步互斥
- 多线程同步与互斥(3)
- Android多线程研究(3)——线程同步和互斥及死锁
- Java多线程间的同步互斥
- JAVA多线程互斥同步例子
- activity进入出去动画
- BCD详细测试说明
- iOS---Url编解码的问题
- ubuntu桌面图片自动切换工具DIY
- Memcached java 简单实例
- Java多线程[3]:线程同步(互斥)
- Redhat下mysql的安装与使用
- 学习笔记 - InputStreamReader封装System.in,最后用BufferedReader封装
- Myeclipse run as 只有Run Configurations
- Kafka简单测试demo
- POJ 3237 - Tree(树链剖分)
- DOM对象和jQuery对象之间的相互转换
- iOS UITableView(表格)
- DefaultServlet int Tomcat