2014-09-25 88 views
0

使用同步(内在锁)关键字锁定被锁定在Java中,我们可以这样做:如何指定对象使用锁定

public void addSum(int a) { 
    synchronized(q) { 
    q.add(a); // q is say a Queue 
    } 
} 

在上面的代码中说,当一个对象试图调用addSum()方法iexaddSum(10),锁将在'q'上保持而不是x。因此,使用同步我们可以锁定除实际调用对象(Class)以外的对象。

下面我正在使用来自java并发包的锁,有没有一种方法来指定锁应该在哪个对象上(即像在上面的代码片断中使用synchronized一样,指定了锁定/同步应该在' q')。但是,下面当我使用锁定时,我没有指定应锁定哪个对象。可以做到吗?

public void addSum(int a) { 
    lock.tryLock(); 
    q.add(a); 
    lock.unlock(); 
} 

我没有参考 - http://docs.oracle.com/javase/tutorial/essential/concurrency/newlocks.html。然而,正在寻找更小的例子来清除我的概念。

回答

1

不,Lock物体与​​的工作方式不同。​​不能在方法调用中启动,并且在该方法调用之外。你已经显示的模式

lock.tryLock(); 
q.add(a); 
lock.unlock(); 

只有在相反的情况下才有可能。 Lock对象通常通过原子地打开/关闭开关/标志来工作,表示他们已经获取或释放了锁。

+0

哦,当我说q.add(a)它实际上不会自己调用。它是队列中的add方法。我将其他方法名称更改为addSum。所以我展示的代码片段实际上并不是以不同的方法开始和结束。 – srock 2014-09-25 05:22:08

+0

所以当我在上面的代码片段中使用Lock时,它锁定了哪个对象?在同步代码段中,它锁定在'q'上。 – srock 2014-09-25 05:27:46

+0

@srock第一条评论:将'synchronized'语法工作为code_的_block,嵌套在方法中或跨越整个方法。你在块的开头获得锁,并在最后释放它。然而,一个'Lock'对象的锁可以跨越多个_codes,进出方法调用,并且潜在地(危险地)永远不会被释放。 – 2014-09-25 05:33:26

1

我想你误解了“锁”这个词的意思。假设这种方法被称为:

void foobar() { 
    synchronized(x) { 
     y.doSomething(); 
    } 
} 

我们说x被“锁定”,而线程处于y.doSomething()电话,但也不阻止其它线程访问字段或更新的x领域。​​关键字意味着一件事,只有一件事。

JVM不允许两个线程同时在同一个对象上同步。

这就是全部它的意思。你如何使用它取决于你。我的例子是使用它来防止y.doSomething()同时在多个线程中被调用,但它只适用于每个对y.doSomething()的调用都以相同的方式受到保护,并且只有在x总是指向同一个对象时才起作用。

java.util.concurrent.ReentrantLock类的工作方式非常相似。 JVM所做的唯一保证是没有两个线程可以同时“锁定”相同的ReentrantLock对象。就是这样。其余的由你决定。


P.S.,第二个示例不测试lock.tryLock()返回的值。这是一个错误。如果lock.tryLock()返回false,那意味着它没有锁定锁定。

+0

完美。最后你提到我没有检查由lock.try lock()返回的布尔值,所以在我上面发布的代码片段中,如果锁定不可用,线程仍然会尝试将整数添加到队列'q “?那是对的吗。所以基本上它会添加到队列'q'而不考虑锁对象? – srock 2014-09-25 13:42:49