Java 并发/多线程教程(十二)-JAVA同步块
本系列译自jakob jenkov的Java并发多线程教程,个人觉得很有收获。由于个人水平有限,不对之处还望矫正!
一个Java同步块标记一个方法或一个代码块作为同步。可以使用Java同步块来避免竞态条件。
在Java中同步的块被标记为Synchronized关键字。Java中的同步块在某些对象上是同步的。在同一对象上同步的所有同步块只能在同一时间内执行一个线程。所有试图进入同步块的其他线程都被阻塞,直到同步块中的线程退出该块.
Synchronized关键字可以用来标记四种不同类型的块:
1、实例方法
2、静态方法
3、实例方法中的代码块
4、静态方法中的代码块
这些块在不同的对象上是同步的。你需要哪种类型的同步块取决于具体的情况
下面是一个同步实例方法
public synchronized void add(int value){
this.count +=value;
}
注意在方法声明中使用synchronized关键字。这告诉Java该方法是同步的。
Java中的同步实例方法在拥有该方法的实例(对象)上同步。因此,每个实例的同步方法都在不同的对象上同步:拥有实例。只有一个线程可以在同步的实例方法中执行。如果存在多个实例,那么每次一个线程可以在每个实例的同步实例方法中执行。每个实例一个线程。
静态方法被标记为同步,就像使用synchronized关键字的实例方法一样。下面是一个Java同步静态方法示例
public static synchronized void add(int value){
count += value;
}
同样在这里,synchronized关键字告诉Java,该方法是同步的。
同步静态方法在类的类对象上同步。由于每个类只存在一个类对象,所以只有一个线程可以在同一个类中执行静态同步方法。
如果静态同步方法位于不同的类中,那么一个线程可以在每个类的静态同步方法中执行。
您不需要同步整个方法。有时最好只同步方法的一部分。在方法内部的Java同步块使这成为可能。
下面是一个非同步Java方法中Java代码的同步块:
public void add(int value){
synchronized(this){
this.count += value;
}
}
这个例子使用Java同步块构造来标记一个代码块作为同步。这段代码现在执行起来就像一个同步的方法一样,请注意Java同步块构造如何在圆括号中使用对象。在这个例子中,使用了“this”,也就是调用add方法的实例。被同步构造的圆括号中的对象称为监视器对象。代码被认为是在监视器对象上同步的。同步的实例方法使用它所属的对象作为监视器对象,只有一个线程可以在同一个监视器对象上同步执行一个Java代码块,下面两个例子在它们被调用的实例上都是同步的。因此,它们在同步方面是等价的:
public class MyClass{
public synchronized void log1(String msg1,String msg2){
log.writeln(msg1);
log.writeln(msg2);
}
public void log2(String msg1,String msg2){
synchronized(this){
log.writeln(msg1);
log.writeln(msg2);
}
}
}
因此,只有一个线程可以在这个示例中的两个同步块中的任何一个中执行。如果第二个同步块在一个不同的对象上被同步,那么一次一个线程就能够在每个方法中执行。
下面是静态方法的两个例子。这些方法在类的类对象上是同步的:方法属于:
public class MyClass{
public static synchronized void log1(String msg1,String msg2){
log.writeln(msg1);
log.writeln(msg2);
}
public static void log2(String msg1,String msg2){
synchronized(this){
log.writeln(msg1);
log.writeln(msg2);
}
}
}
在这两种方法中,只有一个线程可以同时执行。如果第二个同步块在一个不同的对象上被同步,而不是MyClass类,然后一个线程可以同时在每个方法内执行。
这里有一个例子,它启动了两个线程,并让它们都在同一个计数器实例上调用add方法。一次只有一个线程能够在同一个实例上调用add方法,因为这个方法在它所属的实例上是同步的。
public class Counter{
long count = 0;
public synchronized void add(long value){
this.count += value;
}
}
public class CounterThread extends Thread{
protected Counter counter = null;
public CounterThread(Counter counter){
this.counter = counter;
}
public void run() {
for(int i=0; i i++){
counter.add(i);
}
}
}
public class Example {
public static void main(String[] args){
Counter counter = new Counter();
ThreadthreadA = new CounterThread(counter);
ThreadthreadB = new CounterThread(counter);
threadA.start();
threadB.start();
}
}
创建两个线程。相同的计数器实例在它们的构造函数中传递给它们。add()方法在实例上是同步的,因为add方法是一个实例方法,并且标记为synchronized。因此,只有一个线程可以一次调用add()方法。另一个线程将等待第一个线程离开add()方法,然后才能执行该方法本身。
如果这两个线程引用了两个单独的计数器实例,那么就不会同时调用add()方法了。调用的对象应该是不同的对象,因此调用的方法也会在不同的对象上同步(拥有该方法的对象)。因此,通话不会阻塞。这就是它的样子:
public class Example {
public static void main(String[] args){
Counter counterA = new Counter();
Counter counterB = new Counter();
ThreadthreadA = new CounterThread(counterA);
ThreadthreadB = new CounterThread(counterB);
threadA.start();
threadB.start();
}
}
注意两个线程,threadA和threadB,不再引用相同的计数器实例。countA和countB的添加方法在它们的两个拥有实例上是同步的。调用add()在countA将不会阻塞在countB对add()的调用。
同步机制是Java的第一种用于同步对多个线程共享的对象的访问机制。尽管如此,同步机制并不十分先进。这就是为什么Java 5得了一套完整的并发工具类,以帮助开发人员实现更细粒度的并发控制,而不是同步的。
Java IO基础(同步阻塞IO) Java IO是一套Java 用来读写数据(输入和输出)的API,大部分程序都需要处理一些输入,并由输入产生一些输出(PS: 输入和输出是相对CPU而言的,input 就是从外面到CPU,output就是从CPU到外面,CPU是主人公)。java.io 包下有大约80多个类,大概可以分成四组:
Java NIO、BIO、 AIO 与 同步、阻塞、非阻塞、异步IO 简析 我相信大部分人看到这些名词,都是一头雾水的,如果你去搜索引擎搜索,那么恭喜你,你又会被各种文章中的高大上的名词搞得云里雾里。那么,我们应该怎么理清这么名词之间的关系呢? 所谓 同步/异步/阻塞/非阻塞 IO ,是指操作系统中的对 IO 处理的不同方法,而 Java 对这些不同操作方法做了一些包装,由此有了 BIO / NIO / AIO 几种操作接口。 我不想复制一些高大上的概念,只是想尽量好好说话,说清楚他们之间的关系。 有 A、B、C、D 四个线程可以生产文件,假设他们的返回的文件是一样的,对应我们的服务端 有 E、F、G、H 四个线程在随机时间向服务端上传一个文本,并且要求
Java中实现异步转同步的几种方式 Android常见的异步转同步的方式是通过Callback + Handler的方式来完成,常见的例子是在子线程请求网络,成功后调用Callback,然后通过Handler发送消息给主线程,让子线程更新UI。当然了,实际开发还有好多方式可以实现这种操作。
Java多线程(二)、线程的生命周期、线程的同步、Synchronized的使用方法、同步代码块、同步方法、同步机制中的锁、同步的范围、Lock(锁、不会释放锁的操作、单例设计模式之懒汉式(线程安全) Java多线程(二)、线程的生命周期、线程的同步、Synchronized的使用方法、同步代码块、同步方法、同步机制中的锁、同步的范围、Lock(锁、不会释放锁的操作、单例设计模式之懒汉式(线程安全)
相关文章
- Java多线程之线程协作
- Java 网络实例二(查看主机指定文件的最后修改时间、Socket实现多线程服务器程序、Socket连接到指定主机、网页抓取)
- java 多线程并发 synchronized 同步机制及方式
- Java学习密函
- java多线程编程的常见陷阱
- 第十节:详细讲解一下Java多线程,随机文件
- java 常用命令
- JAVA多线程实现的四种方式
- Java学习-080-多线程13:利用Lambda表达式实现线程类的定义
- Java学习-073-多线程06:线程中断 interrupt()
- Java学习-072-多线程05:线程休眠 Thread.sleep()
- java安全编码指南之:锁的双重检测
- java安全编码指南之:Number操作
- 《Java SE》网络编程基础知识归纳。
- Java语言 ASCII to Hex 互转(IOT-示例)
- Java的多线程机制
- 多线程中使用Java集合类
- Java多线程共享数据、同步、通信
- Java程序员面试中的多线程问题
- 我和Java这些年的故事(二)
- Java小白入门200例97之Java Lambda的几种简写方式
- 为什么可以说Java语言是准动态语言?
- Java中多线程、多线程的实现方式、同步代码块的方式
- Java多线程基础(一)---线程安全(synchronized关键字this锁和class锁分析)
- Java MyBatis-Plus 代码生成器
- Java多线程-synchronized同步方法及同步块简述