java如何同步_如何在Java中使用同步 -Manusha

在本文中,您将学习为什么我们需要Java同步,如何编写同步的代码以及有关同步的更重要的要点。

为什么要使用同步?

如果您的代码在多线程环境中运行,则需要同步在多个线程之间共享的对象。否则,可能会发生两种类型的错误。

线程干扰错误

内存一致性错误

Java中的线程干扰是一种情况,当多个同时运行的线程可以访问同一数据时,就会发生这种情况。当线程对同一数据执行不同的操作时,这些操作可能会重叠并在内存中创建不一致的数据。发生这种情况时,数据可能会丢失,损坏或显示意外行为。

在多线程中,一个线程所做的更改可能对其他线程不可见,并且它们对同一共享数据的视图不一致。这称为内存一致性错误。

因此,我们在代码中使用了同步,以避免因这些错误而头痛。您不需要或使用同步共享,如果对象是不可变的,如果所有的线程只能执行只读操作。现在,让我们看看如何同步我们的Java代码。

方法同步

您可以使用synchronized关键字在Java中声明一个同步方法。当线程调用同步方法时,它会在共享数据时自动锁定对象,并在线程完成其任务时释放该对象。因此,如果一个线程运行同步方法,则在同一对象上调用同步方法的所有其他线程将必须等待,直到第一个线程完成。让我们来看一个例子。

class Apple {

synchronized public void getApple() {

for (int i = 0; i < 3; i++) {

System.out.println(i);

try {

Thread.sleep(400);

}

catch (Exception e) {

System.out.println(e);

}

}

}

}

class Tree extends Thread {

Apple apple;

Tree (Apple apple) {

this.apple = apple;

}

@Override

public void run() {

apple.getApple();

}

}

public class SyncEx1 {

public static void main(String[] args) {

Apple obj = new Apple(); //Object of Apple class that is shared amoung threadsTree tree1 = new Tree(obj);

Tree tree2 = new Tree(obj);

tree1.start();

tree2.start();

}

}

getApple()方法在示例中是同步的,一次仅允许一个线程访问该方法。因此,该变量的值i将不会不一致。但是,如果我们只想同步一段代码而不是整个方法,该怎么办?那就是我们需要块同步的时候。

块同步

假设您的方法中有50行代码,但是您只想同步5行。同步块允许您同步方法的任何特定部分。它告诉JVM一次仅允许一个线程访问指定的代码段。

类的synchronizedList()方法java.util.Collections用于返回由指定列表支持的同步列表。因此,每当Iterator使用进行迭代同步列表时,Iterator需要同步使用需求的代码块。让我们看一下示例代码。

import java.util.*;

public class SyncEx2{

public static void main(String []args){

try{

List al = new ArrayList<>();

List movieList = Collections.synchronizedList(al);

movieList.add("StarWars");

movieList.add("Avengers");

movieList.add("Inception");

synchronized(movieList) {// Synchronized blockIterator i = movieList.iterator();

while (i.hasNext())

System.out.println(i.next());// Print Synchronized movie list}

} catch (IllegalArgumentException e) {

System.out.println("Exception thrown : "+ e);

}

}

}

有关同步的重要说明

如果同步静态方法,则锁将位于类上,而不是对象上。因此,无论它有多少对象实例,在这个类静态同步方法中都只能运行一个线程。

在同步方法或块中可以使用3种线程间通信方法。这些都是wait(),notify()和notifyAll()。

您可以使用该wait()方法将当前线程设置为释放锁定,然后等待另一个线程调用该对象的一个notify()或多个notifyAll()方法,或者直到指定的时间过去。

notify()方法将选择并唤醒在此对象上等待的单个线程,并且该notifyAll()方法将唤醒在该对象的监视器上等待的所有线程。

同步有很多限制,它不允许并发访问,可能会导致死锁,并且同步方法的执行速度非常慢。

Java java.util.concurrent在Java 5中引入了该软件包,它可以用作这些问题的解决方案。该软件包提供了一组类,这些类使开发多线程Java应用程序更加容易。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值