java中同步_在Java中的方法同步和语句同步(块同步) - Break易站
Java 多线程
线程主要通过共享对字段的访问和参考字段引用的对象进行通信。这种通信形式非常有效,但可能出现两种错误:线程干扰和内存一致性错误。需要一些同步构造来防止这些错误。以下示例显示了我们需要同步的情况。
在Java中需要同步的情况
请考虑以下示例:
// Java program to illustrate need
// of Synchronization
import java.io.*;
class Multithread
{
private int i = 0;
public void increment()
{
i++;
}
public int getValue()
{
return i;
}
}
class GfG
{
public static void main (String[] args)
{
Multithread t = new Multithread();
t.increment();
System.out.println(t.getValue());
}
}
输出:
1
在上面的示例中,执行了三个操作:
获取变量i的值。
增加获取的值。
并将增加的i值存储到其位置。
这里,
第一个线程获取i的值。(当前值i为0)并将其增加1,因此变量i的值变为1。
现在第二个线程访问i的值为0,因为第一个线程没有将它存储回它的位置。
第二个线程也会增加它并将其存储回其位置。第1个也存储它。
最后,变量i的值为1.但是两个线程的效果应该是2。这就是为什么我们需要同步对共享变量i的访问。
Java是多线程语言,其中多个线程并行运行以完成其执行。我们需要同步共享资源以确保一次只有一个线程能够访问共享资源。
如果一个Object由多个线程共享,则需要进行同步以避免Object的状态被破坏。当Object是可变的时,需要同步。如果共享Object是不可变的,或者共享同一个Object的所有线程只读取未修改的Object状态,则不需要同步它。
Java编程语言提供两种同步习语:
方法同步
语句同步(块同步)
Java中的方法同步
同步方法支持一种简单的策略来防止线程干扰和内存一致性错误。如果一个Object对多个线程可见,则对该Object的所有字段的读取或写入都是通过synchronized方法完成的。
两次调用同步方法不可能进行交错。如果一个线程正在执行synchronized方法,那么在同一个Object上调用synchronized方法的所有其他线程都必须等到第一个线程完成Object。
示例:这显示了多个线程是否在没有同步的情况下访问getLine()方法。
// Example illustrates multiple threads are executing
// on the same Object at same time without synchronization.
import java.io.*;
class Line
{
// if multiple threads(trains) will try to
// access this unsynchronized method,
// they all will get it. So there is chance
// that Object's state will be corrupted.
public void getLine()
{
for (int i = 0; i < 3; i++)
{
System.out.println(i);
try
{
Thread.sleep(400);
}
catch (Exception e)
{
System.out.println(e);
}
}
}
}
class Train extends Thread
{
// reference to Line's Object.
Line line;
Train(Line line)
{
this.line = line;
}
@Override
public void run()
{
line.getLine();
}
}
class GFG
{
public static void main(String[] args)
{
// Object of Line class that is shared
// among the threads.
Line obj = new Line();
// creating the threads that are
// sharing the same Object.
Train train1 = new Train(obj);
Train train2 = new Train(obj);
// threads start their execution.
train1.start();
train2.start();
}
}
输出:
0
0
1
1
2
2
可能有两列火车(两个以上)需要同时使用,因此有可能发生碰撞。因此,为了避免碰撞,我们需要同步多个想要运行的行。
示例:对同一对象的getLine()方法的同步访问
// Example that shows multiple threads
// can execute the same method but in
// synchronized way.
class Line
{
// if multiple threads(trains) trying to access
// this synchronized method on the same Object
// but only one thread will be able
// to execute it at a time.
synchronized public void getLine()
{
for (int i = 0; i < 3; i++)
{
System.out.println(i);
try
{
Thread.sleep(400);
}
catch (Exception e)
{
System.out.println(e);
}
}
}
}
class Train extends Thread
{
// Reference variable of type Line.
Line line;
Train(Line line)
{
this.line = line;
}
@Override
public void run()
{
line.getLine();
}
}
class GFG
{
public static void main(String[] args)
{
Line obj = new Line();
// we are creating two threads which share
// same Object.
Train train1 = new Train(obj);
Train train2 = new Train(obj);
// both threads start executing .
train1.start();
train2.start();
}
}
输出:
0
1
2
0
1
2
Java中的块同步
如果我们只需要执行一些后续代码行而不是方法中代码的所有行(指令),那么我们应该只同步存在所需指令的代码块。
例如,假设有一个方法包含100行代码,但只有10行代码(一个接一个)包含代码的关键部分,即这些行可以修改(更改)Object的状态。因此,我们只需要同步这10行代码方法,以避免对Object状态进行任何修改,并确保其他线程可以在同一方法中执行其余行而不会中断。
import java.io.*;
import java.util.*;
public class Geek
{
String name = "";
public int count = 0;
public void geekName(String geek, List list)
{
// Only one thread is permitted
// to change geek's name at a time.
synchronized(this)
{
name = geek;
count++; // how many threads change geek's name.
}
// All other threads are permitted
// to add geek name into list.
list.add(geek);
}
}
class GFG
{
public static void main (String[] args)
{
Geek gk = new Geek();
List list = new ArrayList();
gk.geekName("mohit", list);
System.out.println(gk.name);
}
}
输出:
1
重点:
当线程进入同步方法或块时,它获取锁定,一旦完成任务并从synchronized方法退出,它就会释放锁定。
当线程进入同步实例方法或块时,它获取对象级别锁定,当它进入同步静态方法或块时,它获取类级别锁定。
如果在synchronized块中使用的Object为null,则Java同步将抛出空指针异常。例如,如果在synchronized(实例)中,instance为null,则它将抛出空指针异常。
在Java中,wait(),notify()和notifyAll()是同步中使用的重要方法。
您不能将java synchronized关键字应用于变量。
不要在同步块上的非final字段上进行同步,因为对非final字段的引用可能随时更改,然后不同的线程可能在不同的对象上同步,即根本不同步。
优点
多线程:由于java是多线程语言,因此同步是实现共享资源互斥的好方法。
实例和静态方法:同步实例方法和同步静态方法都可以同时执行,因为它们用于锁定不同的对象。
限制
并发限制: Java同步不允许并发读取。
降低效率: Java同步方法运行速度非常慢并且会降低性能,因此您应该在绝对必要时同步方法,否则不要同步块仅用于代码的关键部分。
java中同步_在Java中的方法同步和语句同步(块同步) - Break易站相关推荐
- java 方法名相同_Java的方法的重载 :方法名相同,参数类型不同 - Break易站
人类设计语言时,相同的词汇可以表达多种意思.而在Java里面,方法也被设计成这个模式,而区分这些相同方法名的就是方法的参数. Java的方法的重载的特点 方法的重载有下面的特点: 1. 方法名相同,参 ...
- java logging包_用JDK中提供的java.util.logging.*包创建Logger对象----原创
由于项目中用到了Applet与Servlet之间(客户端用Applet.Server端用Servlet)的通信,要求: 1:>客户端与服务端必须出Log. 2:>浏览器在加载Applet时 ...
- java coin介绍_代码示例中的Java 7:Project Coin
java coin介绍 该博客通过代码示例介绍了一些新的Java 7功能,这些项目在Project Coin一词下进行了概述. Project Coin的目标是向JDK 7添加一组小的语言更改.这些更 ...
- java 线程状态_浅析Java中的线程状态
一.线程的5种状态 众所周知,Java的线程状态有5种,分别对应上图中五种不同颜色,下面对这5种状态及状态间的转化做相应的解释: 1. 初始化状态:新建一个线程对象 2. 可运行状态:其他线程调用了该 ...
- java递归优化_在Java中谈尾递归--尾递归和垃圾回收的比较
我不是故意在JAVA中谈尾递归的,因为在JAVA中谈尾递归真的是要绕好几个弯,只是我确实只有JAVA学得比较好,虽然确实C是在学校学过还考了90+,真学得没自学的JAVA好 不过也是因为要绕几个弯,所 ...
- java协程_在Java中使用协程(Coroutine)
各种语言在实现Coroutine方式的支持时,多数都采用了Actor Model来实现,Actor Model简单来说就是每个任务就是一个Actor,Actor之间通过消息传递的方式来进行交互,而不采 ...
- java实现分而治之_并发编程中一种经典的分而治之的思想!!
写在前面 在JDK中,提供了这样一种功能:它能够将复杂的逻辑拆分成一个个简单的逻辑来并行执行,待每个并行执行的逻辑执行完成后,再将各个结果进行汇总,得出最终的结果数据.有点像Hadoop中的MapRe ...
- java 的继承_关于java中的继承
我们都知道Java中的继承是复用代码.扩展子类的一种方式,继承使得Java中重复的代码能够被提取出来供子类共用,对于Java程序的性能以及修改和扩展有很大的意义,所以这是一个非常重要的知识点. 那么对 ...
- java final 类_在Java中,final修饰的类有什么特点
展开全部 关于Java中的32313133353236313431303231363533e4b893e5b19e31333264663736final(2010-09-09 14:19:48)转载▼ ...
最新文章
- STM32单片机如何使用JLINK下载
- C++Primer第五版——习题答案详解(九)
- inconsistent debug frame and source code -Eclipse调试器里看到的代码行数和实际源代码不一致该怎么办
- .propertie文件注释
- 北京交通大学计算机系2018年录取情况,北京交通大学2018年高招录取分数线汇总...
- docker卸载 windows版本_DevOps系列 006 - Docker安装
- Hadoop学习笔记(一):零Linux基础安装hadoop过程笔记
- 麦马计算机科学 UBC工程,2020年UBC文书题目
- 李开复发自前方:From Davos with AI
- Linux 命令(140)—— tree 命令
- 一些常用网站的总结与分享
- docker---dockerfile 编写优化
- 过渡属性transition详解
- .shtml网站解析UnicodeError
- phpstorm配置vcs自动上传代码
- 电脑远程登录控制Android手机-Webkey For Android使用教程
- 列表最后一页的最后一条数据删除之后,页码自动减一
- STRM--用Oracle Streams wizard生成配置脚本
- unityui炫酷动画_Unity_Animation实现UI星星闪耀效果①
- spring诸如方式_回滚诸如在家工作之类的程序时,请谨慎操作
热门文章
- 六耳猕猴并不存在,真假猴王的六耳原来是他!
- SQL基础【二十、索引】(超细致版本,前理论,后实践,应对sql面试绰绰有余)
- AIX卷管理介绍以及利用空闲PP来创建文件系统
- {“errmsg“:“name length invalid rid: 5fbf54ef-3a02c“,“errcode“:300002}
- 鸟哥Linux私房菜(基础篇)——第五章:首次登入与在线求助 man page笔记
- npm的镜像替换成淘宝
- es6笔记 day3---对象简介语法以及对象新增
- C# SQLite事务操作方法分析
- MySQL下perror工具查看System Error Code信息
- 『Linux基础 - 4 』linux常用命令(1)