【发布时间】:2009-10-08 07:04:13
【问题描述】:
对于一个有 100 个并发用户登录的旅行预订 Web 应用程序, 订票和生成“电子票号”应该通过“同步”还是“静态同步”的方式实现?
【问题讨论】:
标签: java multithreading synchronization
对于一个有 100 个并发用户登录的旅行预订 Web 应用程序, 订票和生成“电子票号”应该通过“同步”还是“静态同步”的方式实现?
【问题讨论】:
标签: java multithreading synchronization
那么,你知道静态方法和一般实例方法之间的区别吗?
synchronized 的唯一区别是,在 VM 开始运行该方法之前,它必须获取一个监视器。对于实例方法,获取的锁与您正在调用该方法的对象相关联。对于静态方法,获取的锁与类型本身相关联 - 因此没有其他线程能够同时调用任何其他同步的静态方法。
换句话说,这个:
class Test
{
static synchronized void Foo() { ... }
synchronized void Bar() { ... }
}
大致相当于:
class Test
{
static void Foo()
{
synchronized(Test.class)
{
...
}
}
void Bar()
{
synchronized(this)
{
...
}
}
}
通常我根本不使用同步方法——我更喜欢在私有锁引用上显式同步:
private final Object lock = new Object();
...
void Bar()
{
synchronized(lock)
{
...
}
}
您没有提供足够的信息来确定您的方法应该是静态方法还是实例方法,或者它是否应该完全同步。多线程是一个复杂的问题 - 我强烈建议您阅读它(通过书籍、教程等)。
【讨论】:
Jon 的回答涵盖了您的问题标题中暗示的差异。
但是,我想说都不应该使用来生成票号。假设这些被存储在数据库中的某个地方 - 数据库应该负责在您插入新记录时生成数字(可能是通过自动递增的主键或类似的东西)。
如果您必须在 Java 代码中生成数字,我怀疑如果有 100 个并发用户,同步开销可能会非常明显。如果您在 Java 1.5 或更高版本上运行,我会使用 java.util.concurrent.AtomicInteger 来获取票号,您可以简单地调用它
private static final AtomicInteger ticketSequence;
static
{
final int greatestTicket = getHighestExistingTicketNumber(); // May not be needed if you can start from zero each time
ticketSequence = new AtomicInteger(greatestTicket + 1);
}
public /*static*/ int getNextTicketNumber()
{
return ticketSequence.incrementAndGet();
}
这以比每次需要整数时同步更有效的方式为您提供所需的并发全局唯一性。
【讨论】: