2015-11-01 53 views
0

以下是从Java concurrency in Pratice开始的第一个代码段。我不明白这个类是不是线程安全的?每次线程都不需要调用方法getNext()时,它会首先创建此类的实例?两个线程可以共享这个类的同一实例(barring explicit share)?线程安全:类的实例

@NotThreadSafe 
public class UnsafeSequence { 
private int value; 
/** Returns a unique value. */ 
public int getNext() { 
return value++; 
} 
} 

回答

3

我不明白这个类是不是线程安全的?

你可能已经现在这个问题的答案,但我在这里包括它的完整性。)

的问题是value++声明。这是一个多部分的声明。

  1. 读取value的值。
  2. 读取的值增加1。
  3. 新值存储在value

该序列可以被另一个线程混合使用。说value5。如果两个线程调用getNext()(在同一个实例中),那么在完成后,您会预计value7。然而,如果两个线程以前任何线程完成步骤1和2做第3步,他们都将写入值6value

  • 线程1做第1步 - 读取5
  • 线程2做步骤1 - 将读取5
  • 线程2执行步骤2 - 由1
  • 线程2做步骤3增量5 - 保存的值6
  • 线程1做步骤2 - 增量5通过1
  • 线程1做第3步 - 保存6

就不会在每次一个线程需要调用该方法GETNEXT()的时候,它会 首先创建的这个实例值类?

不是每一次。这将是new UnsafeSequence().getNext()一遍又一遍,这是没有道理的。但也许这不完全是你的意思。每个线程都可以拥有自己的类实例,并且可以调用getNext()。在那种情况下,没有问题。

两个线程可以共享这个类的同一实例(除非明确 份额)?

不,必须以某种方式共享实例。但它可以在你不知情的情况下共享。例如,某些类可能有一个返回UnsafeSequence实例的static方法。你不知道它是否是每次都返回的实例,或者每次调用都创建一个新实例。 除非这是记录在某处。


有关API文档中类是否线程安全的讨论,指的是在线程之间共享实例的情况。如果一个实例不共享,则可以在多线程应用程序中使用它,只需,因为它只有一个线程可用。

1

是明显的2个或更多的线程可以同时访问同一个对象。即当竞争条件发生时,即当多于一个线程争用共享资源时(在您的情况下为UnsafeSequence的同一对象)。

EG:

UnsafeSequence seq = new UnsafeSequence(); 
// both thread instances share same object 
Thread t1 = new MyThread(seq); 
Thread t2 = new MyThread(seq); 
t1.start(); 
t2.start(); 

// run method for above `MyThread` class: 
public void run() { 
    while(some condition) { 
    // some work 
    System.out.println(seq.getNext()); // sequence is unpredictable 
    } 
} 

有不同的线程访问,不同对象实例,就没有线程安全问题。

+0

我无法在那里看到显而易见的内容。谨慎地解释这个问题的背景? – Forkmohit

+0

谢谢。我明白什么时候“分享”,见我问题的最后一句话。 – Forkmohit

+0

对不起,我没有得到最后一部分。你能否详细说明一下。 –

0

由于Java允许多线程语言(其中多个线程并行运行以完成程序执行) 在多线程环境中,Java对象的同步或Java类的同步变得非常重要。

同步是一个功能,它允许一次只有一个线程可以访问资源。它适用于锁定的概念。

ThreadDemo T1 = new ThreadDemo(safeSeq); 
    ThreadDemo T2 = new ThreadDemo(safeSeq); 

在上面的代码中,我们准备了两个线程

这里单独锁
public class UnsafeSequence { 
private int value; 
/** Returns a unique value. */ 
public int getNext() { 
return value++; 
    } 
} 


class ThreadDemo extends Thread { 

UnsafeSequence safeSeq; 

public void run() { 

some code here 

safeSeq.getNext(); 

} 

} 

public class TestThread { 
public static void main(String args[]) { 

    UnsafeSequence safeSeq = new UnsafeSequence(); 

    ThreadDemo T1 = new ThreadDemo(safeSeq); 
    ThreadDemo T2 = new ThreadDemo(safeSeq); 

    T1.start(); 
    T2.start(); 

    } 
} 
1

两个线程可以共享这个类(除明确股)的同一个实例?

我认为这是你误解的根源。

基本上,如果两个线程都使用给定实例的引用,他们正在共享该实例。他们如何设法掌握参考并不重要。 “明确”和其他分享参考方式之间没有真正的区别。

而这个例子的基本假设是两个线程> do <以某种方式管理共享实例。如果他们没有,或者确实只有一个线程,那么线程的安全性或其他类不会成为问题。使用Goetz等人的术语,线程安全性“线程限制”对象无关紧要。)