当前位置: 首页 > 知识库问答 >
问题:

Java 同步和线程

南宫凡
2023-03-14
import java.util.Random;

public class ClassA{
  int a = 0, b = 10;
  Random rand = new Random();

  public synchronized void add(){
      if (a < 10){ 
         a++;
         b--;
      };
  }

  public synchronized void subtract(){
      if (b < 10){ 
         b++;
         a--;
      }
  }
  
  public synchronized boolean check(){
     return a + b == 10;
  }
  
  
  public static void main(String args[]){
      
      ClassA a = new ClassA();
      
      B ba = new B(a);
      B bb = new B(a);
      
       //notice these two threads are not associated with the object a!
      Thread t11 = new Thread(bb);
      Thread t22 = new Thread(ba);
      t11.start(); 
      t22.start();
  }
}


class B implements Runnable{
    ClassA a;
    
    B(ClassA a){
        this.a = a;
    }
   
    @Override
    public void run(){
        while (a.check()){
          if (a.rand.nextInt(2) == 1)
              a.subtract();
          else
              a.add();
      } System.out.print("Out of sync");
    }
}

我试图更好地理解Java多线程。所以,我知道这句话说只有一个线程可以访问一个对象实例,从而调用该实例的方法(例如,在这种情况下,类 class A 中的减方法。

但是,当你仍然有相同的类 A 实例时,会发生什么,但两个线程与不同的类 B 相关联,完全试图调用 a 的方法?我以为不同步的消息永远不会被打印出来,但它确实打印出来了。毕竟,仍然只有一个对象实例 a,这是否意味着同步不适用于此示例?

共有1个答案

楚皓君
2023-03-14

在您的情况下,out of sync永远不会被打印,因为对于您的情况,多线程是正确实现的:通过在方法上使用同步关键字,执行一系列操作并因此不是原子的关键方法的行为类似于原子方法。

假设一个代码块被声明synchronized(x)。进入该代码块的第一个线程获得对象<code>x</code>的锁,并愉快地执行该代码块。

任何尝试进入同一对象 x 上的块的非第一个线程都将通过将线程放入 x 的锁定池来“挂起”。一旦当前具有锁的线程离开同步 (x) 块,锁池中的随机线程将成为执行该块的下一个线程。

当在实例方法上使用< code>synchronized时,它实际上等同于用< code>synchronized (this)包装方法的全部内容。(对于< code>static方法,它将是封闭类的类对象。)

因此,在您的例子中,有一个类<code>A</code>的实例,所有同步都发生在它上面。

如果您想查看不同步消息,请尝试删除同步关键字。然后一段时间后,您应该会看到预期的不同步消息。

旁注:

    < li >因为< code >不同步是一条消息,所以它可能应该打印在< code>System.err上,而不是< code>System.out上。 < li >可以使用< code > a . rand . nextint(2)= = 1 代替< code > a . rand . nextboolean()。 < li >让< code>class A的< code>class B访问字段< code>rand会破坏封装,您可能希望给< code>class A一个方法< code>randomBoolean(),该方法< code >返回rand.nextBoolean(),并从< code>class B中调用该方法< code>randomBoolean()。 < li >相同的变量名在不同的上下文中具有不同的含义可能会引起混淆。在< code>a类中,变量< code>a和< code>b表示两个数字,在其他上下文中,变量< code>a和< code>b指的是< code>a类和< code>b类的实例。考虑将< code > A类字段重命名为其他名称,如< code >数字1和< code >数字2。
 类似资料:
  • 问题内容: 我正在使用Android App,无法将View与硬件同步。让我解释。 1)我从线程1的run方法中基于数组A中存储的随机值(即随机睡眠)对Android的麦克风进行静音和取消静音。 2)我画出反映麦克风静音的蓝色脉冲。这是通过独立的View类完成的。 3)通过从倒数计时器的onTick内调用,我在上面视图中绘制的图形上移动了一条红线。 我以这种方式一个接一个地启动两个线程: 线程1.

  • 主要内容:1 什么是Java 线程同步,2 为什么使用Java线程同步,3 Java同步类型,4 Java线程同步的类型,5 线程互斥,6 Java锁的概念,7 线程并发问题引发数据不一致,8 Java synchronized方法的例子1,9 Java synchronized方法的例子21 什么是Java 线程同步 Java中的同步是控制多个线程对任何共享资源的访问的能力。 Java同步是更好的选择,我们希望只允许一个线程访问共享资源。 2 为什么使用Java线程同步 Java线程同步主要用

  • 我有3节课是这样的: 来源Java语言 任务Java语言 主要的Java语言 当类源的x等于4时,只有一个任务继续递增x,直到x等于8,我们恢复正常。结果如下: 要获得此结果,我需要修复什么?

  • 本文向大家介绍Java 线程同步详解,包括了Java 线程同步详解的使用技巧和注意事项,需要的朋友参考一下 Java 线程同步根本上是要符合一个逻辑:加锁------>修改------>释放锁 1、同步代码块 示例如下: 示例中希望按照顺序依次输出整数。 通常同步代码块是需要锁定的对象,一般是需要并发访问的共享资源,任何线程在修改指定资源之前都首先对该资源加锁,在加锁期间其它线程无法修改该资源。从

  • 我想更多地了解线程睡眠解析是如何工作的,以及它与睡眠()解析之外的内容有什么联系。 我知道它是由操作系统定义的,而在Windows上通常是15ms。我最近环顾四周无法确认这一点,但我依稀记得这个15ms是由操作系统循环的,并且对所有线程都是“全局的”,这意味着15ms不是线程可以Hibernate的最短时间,而是最大Hibernate时间(1)。对吗?所有操作系统都一样吗(超过持续时间)? 我想不

  • 下面的代码创建了一个新的custom um < code > Thread ,并等待线程结束,直到主线程再次激活。 > < li >我不太明白它是如何工作的。为什么< code > myth read . wait();立即接到电话? < li> 为什么不改用< code>Thread.join()? 公共静态void main(String[] args) {