我只是遇到一个与并发相关的问题,其逻辑流程是当客户端(称为Oracle Forms)提交请求(称为并发程序)并调用plsql过程时,此过程最终将调用java静态方法。
我发现当我在同一时间或非常短的间隔(例如1秒)内提交两个请求时,会注意到一些并发问题。
java方法是做一些事情的起点,从数据库中搜索建议应该将哪些记录插入到数据库中。
问题在于,它们会导致重复的结果,因为当我查询时,两个请求都可以很好地插入新记录。
我尝试在静态java方法中添加synchronized
,但这并不能解决这个问题,为什么呢?
我的工作是:
public static synchronized void execute
请注意,插入将在plsql中调用,这意味着如果只是同步java方法,我会进行不充分的同步。但是当我查看日志时,它会显示同一秒内运行的两个请求,我不认为这是正常的!因为查询数据库和做建议是耗时的。
为了使java方法非常耗时,我添加了一个代码调用Thread.sleep(5000)
,并记录此代码后的时间并记录线程ID。
惊喜地看到Thread
id为1!此外,他们通过睡眠的时间也在同一时间。那是为什么?
我该怎么做才能解决问题?对java方法或pl sql的任何锁定?
PS:我现在正在尝试使用DMBS_LOCK
,这似乎有效,但我仍然希望知道java方法未同步的原因。
答案 0 :(得分:2)
我不知道Oracle DB中的JVM是如何实现的,但是因为(至少在一些常见配置中)每个数据库连接都有自己的服务器进程,那么如果嵌入了一个单独的JVM对于每一个,同步块不会对你有好处。您需要使用数据库锁。
答案 1 :(得分:0)
假设对Java静态方法的调用是在同一个类加载器中完成的,那么synchronized
就是你所需要的。
您的日志记录可能有问题。你究竟是如何记录的?
关于数据库查找“耗时”的陈述并不令人信服。例如,数据库倾向于缓存数据。
简而言之:如果根据您的定义,“原子操作”是查找+插入的组合,那么您应该“同步”两者。获取数据库锁似乎是一种合理的方法。