对资源的同步访问

时间:2011-11-08 19:07:39

标签: java concurrency synchronization

假设我们有一些资源(磁盘上的文件),我们必须写入不同线程产生的字节。这些线程由某些进程生成,该进程侦听某些事件并在每次事件发生时生成线程。因为我们只有一个资源,所以我们必须同步执行写操作的类的方法:

    synchronized void write(byte [] bytes) {
       //write data to file
    }

或创建一些互斥:

Object mutex = new Object();
void write(byte [] bytes) {
   synchronized(mutex) {
      //write data to file
   }
}

现在假设我们有非常旧的硬盘驱动器,因此执行写操作的速度太慢。我们一天有好几次发生了大量的事件。所以线程会像资源队列一样。所以我有下一个问题:

  1. 这样的队列可以多长时间?
  2. 如果有多个线程在等待资源和资源 已经释放了第一个占用资源的线程。将 它是FIFO原理吗?
  3. 如果线程有不同的优先级,情况会如何变化?
  4. 如果资源是DataSource对象,它产生Connection个参与连接池的对象,它是否与上面的文件相同?

3 个答案:

答案 0 :(得分:3)

  1. 队列的长度是被阻止的线程数。如果你继续创建线程并且它们都以书面形式完成阻止,那么你很快就会让系统陷入困境。您当然应该使用线程池,重用线程而不是创建它们,并在队列中有太多事件时阻塞。见Executors
  2. 不,这不是FIFO。订单未定义。如果你想要FIFO,你可能想要使用公平ReentrantLock。但是基本同步或不公平锁定会更耗时。
  3. 依赖于平台,没有确定性行为。
  4. 这一切都取决于数据源的实现。它可能使用公平算法或仅使用公平锁定。或者它可能只是使用同步而不公平。如果足够详细,您需要阅读数据源的文档。

答案 1 :(得分:2)

  1. 使用此设计的等待线程数量没有理论上的限制。
  2. 不可预知的。 java的隐含规范不需要为这种类型的简单锁定进行线程排序。实际的顺序将取决于JVM和主机架构的实现,但您永远不应该依赖于此。
  3. 这取决于线程引擎,可能会也可能不会产生影响。但是,JVM线程引擎将尝试在降低之前调度高优先级线程,并且实际上将抢占已经运行的低优先级线程。
  4. 就你的主题而言,两者完全相同。线程依赖于同步机制来控制资源使用,确切的资源不应该改变它们的行为,除非连接比文件慢,否则可能需要更长的等待时间。

答案 2 :(得分:2)

从我有限的理解:

1-它可能非常大,受系统可以拥有的线程数限制(我认为它受最大线程数或某些OS本机资源限制的限制)。我见过100 +。

2-是的,线程应以FIFO方式获取资源。

3-不,具有较高优先级的线程可能会更快地排队,但是在排队后,它们的位置是固定的。

4-数据源可能有所不同,它主要取决于池的实现。我认为Apache的dbcp(如Tomcat中所示)表现得这样,只是如果池在设定的时间内无法分配连接,则可能会触发超时。

希望这有帮助。