简体   繁体   English

如何实现一个可以使用Java安全递增的多线程变量?

[英]How do I implement a multi-threaded variable that I can safely increment using Java?

In my program I have one thread incrementing a supply variable by 2, then another thread takes a random number of supply from a supply class. 在我的程序中,我有一个线程将供应变量递增2,然后另一个线程从供应类中获取随机数量的供应。 The supply class can only store up to 5 values and because the sleep and supply requests are random, the supply count can increment over it's max limit. 供应类最多只能存储5个值,并且由于睡眠和供应请求是随机的,因此供应计数可以超过其最大限制。

What I'm trying to make sure is that it doesn't go over that limit. 我要确保的是它没有超过这个限制。

Is there a better way to do this? 有一个更好的方法吗?

(pseudocode) (伪代码)

  1. increment supply by 2 增加供应2
  2. if supply is more than max then assign supply to max 如果供应量超过最大值,则将供应量分配给最大值

Here is the code: 这是代码:

private int MAX = 5;
private int supply = 0;
public void run()
{
    while(true) {
      supply = supply + 2;
      if(supply > MAX) 
          supply = MAX;
    }
}

You could use a public synchronized incSupply() method which is used to increment the supply variable: 您可以使用公共同步的incSupply()方法来增加供应变量:

public synchronized void incSupply()
{
    // Code borrowed from Jean-Bernard Pellerin.
    int temp = supply + 2;
    if (temp > MAX)
        temp = MAX;
    supply = temp;
}

Note that you need to use synchronized also for other methods that read/write from/to the 'supply' variable. 请注意,对于从'supply'变量读取/写入的其他方法,您还需要使用synchronized。

int temp = supply + 2;
if (temp > MAX)
  temp = MAX;
supply = temp;

This is still not thread-safe though. 但这仍然不是线程安全的。 You should look into locks and synchronization. 你应该研究锁和同步。

If you have more than one thread you should declare your common resource,(meaning other threads execute commands on that variable) in your case i guess would be the supply, as synchronized. 如果你有多个线程,你应该声明你的公共资源,(意味着其他线程对该变量执行命令)在你的情况下,我猜是供应,如同步。 and use fine-grained synchronization 并使用细粒度同步

synchronized(this) {
     supply = supply+2
 }

I dont entirely understand this part of your question: and the other thread takes a random number of supply from the supply class . 我不完全理解你的问题的这一部分: and the other thread takes a random number of supply from the supply class Does this mean the consuming thread can take a random number of values from the supply class, or a value which is a random number? 这是否意味着消费线程可以从供应类中获取随机数量的值,或者是随机数的值?

In any case, you have a resource which requires mutually exclusive access, so you need to ensure that only one thread can modify it. 在任何情况下,您都有一个需要互斥访问的资源,因此您需要确保只有一个线程可以修改它。 In java, this is easily done by requesting a intrinsic lock on the instance being modified, only one thread can hold this lock at any given time. 在java中,这可以通过在被修改的实例上请求内部锁来轻松完成,只有一个线程可以在任何给定时间保持此锁。 Now, when a thread encounters a synchronized block (as per Stelsavva's example) it automatically will try and obtain the intrinsic lock on whichever instance this represents, and hold it until the end of the block. 现在,当一个线程遇到一个synchronized块时(根据Stelsavva的例子),它会自动尝试在this代表的任何一个实例上获得内部锁,并保持它直到块的结尾。 If any other thread encounters the block, while another thread is holding the lock, it will wait until the lock is released by the other thread. 如果任何其他线程遇到该块,而另一个线程持有该锁,则它将等待另一个线程释放该锁。

Hence, the execution is of the block is synchronised and you wont have problems with interleaving. 因此,块的执行是同步的,你不会遇到交错问题。

Use a Semaphore with five permits. 使用具有五个许可证的信号量 Somewhat counterintuitively, I think the permit would represent the permission to store a supply, so the first thread would need to acquire permits to store the supplies. 有点违反直觉,我认为许可证代表了存储供应的许可,因此第一个线程需要获得存储供应品的许可证。 When the second thread takes supplies, it releases this many permits. 当第二个线程获取耗材时,它会释放许多许可证。

The simplest solution is to use AtomicInteger without going throughout the trouble of synchronizing the increment: 最简单的解决方案是使用AtomicInteger而不会遇到同步增量的麻烦:

private int MAX = 5;
private AtomicInteger supply = new AtomicInteger(0);
public void run()
{
    while(true) {
      if(supply.addAndGet(2) > MAX) 
          supply.set(MAX);
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在Java中实现多线程PID控制器? - How can I implement a multi-threaded PID controller in Java? 如何为多线程Java服务器实现Observer设计模式? - How do I implement Observer design pattern for a Multi-Threaded Java server? 我怎样才能使多线程应用程序分布在Java中? - how can i make multi-threaded application distributed in java? 如何取消多线程繁忙任务的未来? - How can I cancel the Future of a multi-threaded busy task? 如何使这个Java代码正常运行? [多线程,竞争条件] - How do I make this Java code operate properly? [Multi-threaded, race condition] 如何复制ArrayList <T> 在java多线程环境中? - How do I copy ArrayList<T> in java multi-threaded environment? 如何保持多线程Java / Scala应用程序运行? - How can I keep a multi-threaded Java/Scala application running? 如何在Java中实现多线程计时器任务? - How to implement a multi-threaded timer task in java? Java:多线程映射:实现如何比较? - Java: multi-threaded maps: how do the implementations compare? 如果我没有在Java中关闭BufferedReader会发生什么? (在多线程程序中读取流类型) - What happens if I do not close BufferedReader in java? (Stream type reading in multi-threaded program)
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM