Java中对象的锁定机制

Java中对象的锁定机制,java,multithreading,Java,Multithreading,假设客户有一张信用卡。他有x金额的余额,他正在购买y有价值的物品(yx但z你的建议不合适。你不能确定在检查和更新之间不会发生上下文切换 唯一的方法是同步。我更喜欢使用读写锁,这有助于为读写锁定它,这很好,因为您可以为每个资源单独设置读写锁: ReadWriteLock readWriteLock = new ReentrantReadWriteLock(); readWriteLock.readLock().lock(); // multiple readers can enter

假设客户有一张
信用卡
。他有
x
金额的余额,他正在购买
y
有价值的物品
(yx但z你的建议不合适。你不能确定在检查和更新之间不会发生上下文切换


唯一的方法是同步。

我更喜欢使用
读写锁
,这有助于为读写锁定它,这很好,因为您可以为每个资源单独设置读写锁:

ReadWriteLock readWriteLock = new ReentrantReadWriteLock();


readWriteLock.readLock().lock();

    // multiple readers can enter this section
    // if not locked for writing, and not writers waiting
    // to lock for writing.

readWriteLock.readLock().unlock();


readWriteLock.writeLock().lock();

    // only one writer can enter this section,
    // and only if no threads are currently reading.

readWriteLock.writeLock().unlock();
ReadWriteLock
内部保留两个锁实例。一个保护读访问,一个保护写访问

据我所知,一种方法是我们可以保留原始余额的副本 我们可以在更新余额之前检查当前值。如果 值与原始值相同,然后我们可以确保其他线程 不会改变平衡。如果平衡不同,那么我们必须撤销 我们的计算

听起来像是什么和做什么


一种更容易理解的方法是在您的
信用卡
类上使用
synchronized
方法,您的代码将调用这些方法来更新余额。(一个对象上的
synchronized
方法在任何时候都只能执行一个。)


在本例中,听起来您需要一个
公共同步布尔makePurchase(int-cost)
方法,成功时返回
true
,失败时返回
false
。目标是对象上的任何事务都不应需要多个方法调用-正如您所意识到的,您不希望对
信用卡
进行两次方法调用(
getBalance()
和更高版本的
setBalance()
)由于潜在的竞争条件,您正在谈论的内容听起来像是您乐观地假设没有其他线程会修改您的事务所依赖的数据,但您有一种机制来检测它们是否有

java.util.concurrent.atomic
包中的类型有助于构建无锁解决方案。它们实现了高效的比较和交换操作。例如,
AtomicInteger
引用允许您访问以下内容:

AtomicInteger balance = new AtomicInteger();

…

void update(int change) throws InsufficientFundsException {
  int original, updated;
  do {
    original = balance.get();
    updated = original + change;
    if (updated < 0)
      throw new InsufficientFundsException();
  } while (!balance.compareAndSet(original, update));
}
AtomicInteger余额=新的AtomicInteger();
…
无效更新(整数更改)引发的FundsException不足{
int原件,已更新;
做{
原始=balance.get();
更新=原始+变更;
如果(更新<0)
抛出新的不足基金异常();
}而(!balance.compareAndSet(原始,更新));
}
正如您所看到的,这种方法受制于一个活锁线程条件,其他线程不断地改变平衡,导致一个线程永远循环。实际上,应用程序的细节决定了活锁的可能性


显然,这种方法很复杂,而且有很多陷阱。如果您不是并发专家,那么使用锁来提供原子性会更安全。如果
synchronized
块中的代码不执行任何阻塞操作(如I/O),则锁定通常可以很好地执行。如果关键部分中的代码具有确定的执行时间,那么你最好使用锁。

听说过
synchronized
?@Rahulbobbhate我在问题中添加了一部分,其他线程只需等待它尝试访问同一张信用卡-这是不太可能的。@AlexeiKaigorodov是的,你是正确的。但如果这是大规模的,如果有更多的过程,那么问题就会出现。我期待了解更多有关这方面的信息。感谢您的回答,+1最好锁定资源,而不仅仅是锁定方法。。因为这仍然会导致
竞争条件