同步方法
同步方法接近于临界区的概念,同一时间只能运行一个线程,一个类中所有的同步方法同一时间内只能有一个线程在一个方法体内执行。例如:
public class Resource {
public synchronized String get(){
//..........
return null;
}
public synchronized void put(String str){
//..........
}
}
当一个线程执行get()时,其他线程既不能执行get(),也不能执行put()。
同步块
同步会造成系统性能的下降,为缩小同步的范围,java提供同步块功能。
public class Resource {
public String get(){
//..........
Synchronized(this){
//………….
}
return null;
}
public void put(String str){
//..........
Synchronized(this){
//………….
}
}
}
同步块与同步方法的意义是一样的,但同步块应用范围更广,使用起来更灵活。同步块类似于锁,可以把synchronized(this)中的this当成一个锁,进入同步块上锁,离开同步块时解锁。使用同一个锁的同步块同一时间内只能有一个同步块被执行。如上面的示例,get中的同步块被执行时,其他的线程既不能进入get同步块,也不能进入put同步块。
如果在Synchronized后面使用不同的对象,则相当于使用多个锁,只有使用相同锁的同步块不能同时执行,使用不同锁得同步块可以同时执行。比如:
private static Object obj1 = new Object();
private static Object obj2 = new Object();
public void test1() {
System.out.println("test1 enter");
synchronized (obj1) {
for (int i = 0; i < 4; i++) {
System.out.println("test1 excute");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
System.out.println("test1 exit");
}
public void test2() {
System.out.println("test2 enter");
synchronized (obj2) {
for (int i = 0; i < 4; i++) {
System.out.println("test2 excute");
try {
Thread.sleep(400);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
System.out.println("test2 exit");
}
以上代码执行结果
test1 enter
test1 excute
test2 enter
test2 excute
test2 excute
test1 excute
test2 excute
test1 excute
test2 excute
test1 excute
test2 exit
test1 exit
可以看到test1 与test2是交互执行的。也就是说同时不会有两个线程在test1或是在test2中执行,但同时可以一个线程执行test1,一个线程执行test2。
等待和通知方法
在JDK1.5之前,Java提供的主要线程同步技术只有等待/通知函数配合同步方法或同步块,suspend或resume早就不提倡使用。
Wait()和notify()/notifyAll()是java.lang.Object类的方法,java中任一个类都是Object的子类,换句话说,Java中任一个类都提供wait()notify()/notifyAll()方法。我们来看一下等待通知函数的使用。
我们以一个经典的多线程场景“生产者/消费者”来说明如何使用等待通知函数
1、 等待通知函数只能应用在同步方法体或同步块内。也就是说,调用某个对象的wait()notify()方法前必须获得这个对象的监视器(monitor)
2、 调用某个对象的Wait()方法时,相当于把当前线程放到这个对象的等待区中(可以假想这是对象的一个Collection类型的属性,把线程对象放到这个Collection中),然后挂起这个线程,最后释放这个对象的监视器。Notify()/notifyAll()方法则刚好相反,从对象的等待区中取出线程,恢复,最后释放这个对象的监视器。Notify()notifyAll()的区别是notify从等待区中拿出一个线程并且激活,而notifyAll是从等待区中拿出所有线程并且激活。
使用同步块和等待通知方法的“生产者/消费者”示例
public class SynchronizedSample ...{
//模拟资源
private List<String> resource=new ArrayList<String>();
volatile int i=0;
boolean exit = false;
public SynchronizedSample()...{
Thread consumer = new Thread(new Consumer());
Thread producer = new Thread(new Producer());
consumer.start();
producer.start();
}
public void exit()...{
this.exit = true;
}
public static void main(String[]args)...{
SynchronizedSample sample = new SynchronizedSample();
try ...{
Thread.currentThread().sleep(2000);
} catch (InterruptedException e) ...{
return;
}
sample.exit();
}
public class Consumer implements Runnable ...{
public void run() ...{
while (!exit) ...{
synchronized (resource) ...{
while (resource.isEmpty()) ...{
try ...{
//调用resource的等待方法
resource.wait();
} catch (InterruptedException e) ...{
return;
}
}
System.out.println("Consumer take: "+resource.remove(0));
//调用resource的通知方法
resource.notifyAll();
}
}
}
}
public class Producer implements Runnable ...{
public void run() ...{
while (!exit) ...{
synchronized (resource) ...{
while (resource.size() >= 10) ...{
try ...{
resource.wait();
} catch (InterruptedException e) ...{
return;
}
}
String r = "Resource"+i++;
System.out.println("Producer put: "+r);
resource.add(r);
resource.notifyAll();
}
}
}
}
}
分享到:
相关推荐
在《秒杀多线程系列》的前十五篇中介绍多线程的相关概念,多线程同步互斥问题《秒杀多线程第四篇一个经典的多线程同步问题》及解决多线程同步互斥的常用方法——关键段、事件、互斥量、信号量、读写锁。为了让大家...
在char01包里放置Java多线程基本知识的代码。内容如下: 如何使用多线程 如何得到多线程的一些信息 如何停止线程 如何暂停线程 线程的一些其他用法 在char02包里放置了Java对变量和对象并发访问的知识的代码...
锁正是基于这种思路实现的一种线程同步机制。 在对共享数据加锁后,每个线程在访问共享数据时必须先申请相应的锁。一旦获得锁后,就可以访问共享数据,并且一个锁同一时刻只能被一个线程持有,这意味着获得锁后不会...
主要参考资料:java并发编程的艺术、Java并发——同步工具类 二、CountDownLatch(同步倒数计数器)–不仅仅用于多线程 1.作用:允许一个或多个线程等待其他线程完成操作。 CountDownLatch的构造函数...
Lock类是Java类来提供的功能,丰富的api使得Lock类的同步功能比synchronized的同步更强大。本文对此进行详细介绍,下面跟着小编一起来看下吧
在进行多线程开发时最令人头痛的问题估计就是对共享资源的控制了吧,今天就让我们谈一谈这个问题吧。 共享资源顾名思义就是需要被多个线程使用的资源,但是很多情况下我们是不能允许多个线程同时使用这个资源的。这...
本例将模仿经典的线程同步互斥例子——生产者和消费者问题,来演示 java 强大的多线程机制。生产者和消费者共享一个数据,当数据为0 时,消费者不可访问,生产者可访问数据,每次访问数据加1;当数据到达100 时,...
最后还给出了一个聊天程序实例和一个数据表操作窗口实例,将Swing、UDP、Java集合类、线程同步、接口和JDBC编程有机地结合起来,展示了开发一个简单程序的典型步骤。 本书适合广大想学习一门编程语言的读者、没有...
浏览器就是一个很好的多线程的例子,在浏览器中你可以在下载JAVA小应用程序或图象的同时滚动页面,在访问新页面时,播放动画和声音,打印文件等。 多线程的好处在于可以提高CPU的利用率——任何一个程序员都不希望...
add 实验一:多线程/2.Runnable接口. 实验八:JDBC数据库编程二——存储过程与函数 add 实验八:JDBC数据库编程二——存储过程与函数/2.addTwoNumAndReturn. 实验十:Socket编程 add 实验十:Socket编程/...
浏览器就是一个很好的多线程的例子,在浏览器中你可以在下载JAVA小应用程序或图象的同时滚动页面,在访问新页面时,播放动画和声音,打印文件等。 多线程的好处在于可以提高CPU的利用率——任何一个程序员都不希望...
JAVA 数据在内存中的执行流程执行规则:Read和Load ,Store和Write必须顺序执行,但是不必连续执行;一个变量同时只能被一条线程操作,可以被多条
1、基础概念多线程与并发(一)——概述、线程状态进程与线程区别?多线程与并发(二)——线程同步、线程协作同步方法和同步代码块?多线程与并发(三)——JUC概述、
030904_【第9章:多线程】_同步与死锁笔记.pdf 030905_【第9章:多线程】_线程操作案例——生产者和消费者笔记.pdf 030906_【第9章:多线程】_线程生命周期笔记.pdf 031001_【第10章:泛型】_泛型入门笔记.pdf ...
Java语言支持多个线程的同时执行,并提供多线程之间的同步机制【4】。 通过一个学期的学习,对Java有了一定的了解,为了巩固所学知识,编写一个剪刀石 头布游戏。 1剪刀石头布游戏设计思路阐述 在设计游戏时,我们...
目前只支持两个客户端进行网络对战,多个玩家还有如线程同步问题等。两个客户端可以在同一台电脑上运行。 Ch04:多媒体展示系统 –网络游鱼 安装JDK、配置环境变量,打开Eclipse导入ch04项目,运行server....
│ │ 9.JAVA并发编程之多线程并发同步业务场景与解决方案.wmv │ │ │ ├─10.微服务架构之Spring Cloud Eureka 场景分析与实战 │ │ 10.微服务架构之Spring Cloud Eureka 场景分析与实战.wmv │ │ │ ├─11....
Java局域网通信——飞鸽传书源代码,大家都知道VB版、VC版还有Delphi版的飞鸽传书软件,但是Java版的确实不多,因此这个Java文件传输实例不可错过,Java网络编程技能的提升很有帮助。 Java聊天程序,包括服务端和...
Java局域网通信——飞鸽传书源代码,大家都知道VB版、VC版还有Delphi版的飞鸽传书软件,但是Java版的确实不多,因此这个Java文件传输实例不可错过,Java网络编程技能的提升很有帮助。 Java聊天程序,包括服务端和...
第8章Java的多线程机制266 8.1线程的概念266 8.1.1多线程的特点266 8.1.2线程的状态267 8.2Thread类268 8.2.1Thread类的构造方法268 8.2.2Thread类的常用方法268 8.3多线程程序的编写269 8.3.1利用Thread的...