Java 确保一个类中只有一个线程
我有一个DAO类,它有多个更新DB表的方法。这些方法在整个代码库中的许多不同位置以许多不同的顺序被调用Java 确保一个类中只有一个线程,java,multithreading,concurrency,Java,Multithreading,Concurrency,我有一个DAO类,它有多个更新DB表的方法。这些方法在整个代码库中的许多不同位置以许多不同的顺序被调用 public class Dao { public synchronized updateA() public synchronized updateB() public synchronized updateC() public synchronized getA() public synchronized getB() public synchronized get
public class Dao {
public synchronized updateA()
public synchronized updateB()
public synchronized updateC()
public synchronized getA()
public synchronized getB()
public synchronized getC()
}
我遇到一个问题,Class1希望依次调用getA()
、getB()
、和getC()
。三个表A、B和C是相关的,所以我需要在一个时间点同步它们的状态
然而,在Class1调用getA()
之后和调用getB()
之前,另一个线程上的Class2跳入并调用updateB()
,这会破坏一些东西
有没有可能在有任何线程的情况下锁定整个DAO类,并且只在完成后才解锁它
我已经尝试在DAO类中放置一个静态ReentrantLock并从Class1锁定它,但我不确定如何从那里开始
我已经做到了以下几点:
public class Class1 {
public void check() {
dao.daoLock.lock();
dao.getA();
dao.getB();
dao.getC();
dao.daoLock.unlock();
}
}
public class Dao {
public static final daoLock = new ReentrantLock();
public synchronized updateA() {
daoLock.lock();
// Do stuff...
}
public synchronized updateB() {
daoLock.lock();
// Do stuff...
}
public synchronized updateC() {
daoLock.lock();
// Do stuff...
}
public synchronized getA() {
daoLock.lock();
// Do stuff...
}
public synchronized getB() {
daoLock.lock();
// Do stuff...
}
public synchronized getC() {
daoLock.lock();
// Do stuff...
}
}
我不确定解锁的位置。如果我把它放在每个DAO类方法中,它会让其他线程进入,不是吗
这里有更好的解决方案吗?您试图在客户端同步对数据库的访问,而客户端根本不适合这样做。如果另一个客户同时写了一封信呢 最好将这种同步留给数据库本身,使用事务(,)
即使您没有多个客户机,而且永远不会,使用事务也是一个更好的解决方案。否则,即使只是执行读取操作,所有线程也会相互阻塞,这在原则上可以同时进行。您试图在客户端同步对数据库的访问,但这从根本上说是错误的。如果另一个客户同时写了一封信呢 最好将这种同步留给数据库本身,使用事务(,)
即使您没有多个客户机,而且永远不会,使用事务也是一个更好的解决方案。否则,即使只是读取,所有线程也会相互阻塞,这在原则上可以同时发生。除了Thomas给出的好答案外,这里还有另一个值得注意的方面:接口的编写方式应该使正确的操作变得容易;而且很难做错事 意思:如果某个操作要求您按顺序并以“整体锁定方式”调用a()、b()、c(),那么:您的接口上没有a、b、c,而是提供了一个方法abc()。。。获取锁,调用a、b、c并释放锁 因此,您应该退一步,从一个角度来看类的接口;或者更具体一点——从“单一责任原则”的角度考虑
换句话说:拥有一个提供许多完全“分离”方法的类;其中一些甚至需要“以非常特定的方式一起使用”,这是一种清晰的设计气味;因此,另一个指示是,您最好后退一步,回顾此设计。除了托马斯给出的好答案外,还有一个值得关注的方面:接口的编写方式应该使正确的事情变得容易;而且很难做错事 意思:如果某个操作要求您按顺序并以“整体锁定方式”调用a()、b()、c(),那么:您的接口上没有a、b、c,而是提供了一个方法abc()。。。获取锁,调用a、b、c并释放锁 因此,您应该退一步,从一个角度来看类的接口;或者更具体一点——从“单一责任原则”的角度考虑
换句话说:拥有一个提供许多完全“分离”方法的类;其中一些甚至需要“以非常特定的方式一起使用”,这是一种清晰的设计气味;因此,另一个迹象表明,您最好后退一步,检查一下这个设计。是否可以添加一个
同步更新a和B()
方法,以原子方式更新a和B?或者更改策略,以便在调用站点(可能在类实例本身上)执行同步?或者添加一个原子更新a和B的synchronized updateA和B()?或者更改策略,以便在调用站点(可能在类实例本身上)完成同步?