确保 Java 同步锁按顺序获取?

发布于 2024-08-12 17:37:03 字数 130 浏览 2 评论 0原文

我们有两个线程通过同步方法访问一个列表。我们能否

a) 依靠运行时来确保每个人都将根据他们尝试的顺序接收对方法的访问权限,或者

b) 虚拟机是否遵循任何其他规则

c) 是否有更好的方法来序列化请求?

we have two threads accessing one list via a synchronized method. Can we

a) rely on the run time to make sure that each of them will receive access to the method based on the order they tried to or

b) does the VM follow any other rules

c) is there a better way to serialize the requests?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

ヤ经典坏疍 2024-08-19 17:37:03

不,synchronized 将以任何顺序提供访问权限(取决于 JVM 实现)。在某些情况下,这甚至可能导致线程饥饿。

您可以使用 ReentrantLock< 来确保顺序/a> (自 Java 5.0 起)带有 fair=true 选项。 (Lock lock = new ReentrantLock(true);)

No, synchronized will give access in any order (Depends on the JVM implementation). This could even cause Threads to starve in some scenarios.

You can ensure the order by using ReentrantLock (since Java 5.0) with the fair=true option. (Lock lock = new ReentrantLock(true);)

烟若柳尘 2024-08-19 17:37:03

不,您无法确定对同步方法的两次调用是否会按顺序发生。该顺序未指定且依赖于实现。

这是在 17.1 锁 部分中定义的JLS。请注意,这没有说明等待锁的线程应该获得访问的顺序。

No you cannot be sure that two calls to a synchronized method will occur in order. The order is unspecified and implementation dependent.

This is defined in the 17.1 Locks section of the JLS. Notice that is says nothing about the order in which threads waiting on a lock should gain access.

刘备忘录 2024-08-19 17:37:03

您不能依赖每个线程调用特定方法的顺序。如果只有两个线程可能是的。但想象一下,如果有 3 个线程并且 1 个线程已经获得了访问权限。其他 2 个线程在尝试访问时将等待,其中任何一个线程都可以被授予访问权限,并且这不取决于它们调用此方法的顺序。
所以,不建议依赖命令。

You can't rely on the order in which the particular method is called from each threads. If it is only two threads may be yes. But imagine if there are 3 threads and 1 thread already acquired access. The other 2 threads when they try to access will wait and any one of them can be awarded the access, and this does not depend on the order in which they called this method.
So, it is not suggested to rely on the order.

你的呼吸 2024-08-19 17:37:03

c) 有没有更好的方法来序列化请求?

您是否有机会使用列表作为队列,即使用模式是否看起来像这样?

while (some condition) {
    synchronized(theList){
        anItem = get and remove an element from theList
    }
    do some work with anItem
}

如果是这样,您可能需要查看 BlockingQueue 接口而不是使用您自己的锁定方案。实现(如 ArrayBlockingQueue)具有公平性等设置。

c) is there a better way to serialize the requests?

Are you by any chance using the list as a queue, i.e., does the usage pattern look something like this?

while (some condition) {
    synchronized(theList){
        anItem = get and remove an element from theList
    }
    do some work with anItem
}

If so, you may want to look at the BlockingQueue interface instead of using your own locking schemes. The implementations (like ArrayBlockingQueue) have settings for fairness and more.

山色无中 2024-08-19 17:37:03

我总是将同步保留给应用程序服务器或引擎,除非定义自己的强度

I always leave syncs to app server or engine unless defining own intensity

固执像三岁 2024-08-19 17:37:03

我已经用几种仪器解决了类似的问题。我试图解决的问题是乒乓服务。两个线程,一个打印 Ping,另一个打印 Pong。但它们必须是连续的。 (没有双 Ping 或双 Pong)

我将在这里放置一个实现,但您可以查看其他实现(目前有 6 或 7 种不同的方式)
https://github.com/tugrulkarakaya/pingpong

import java.util.concurrent.*;

public class Method2CyclicBarrier {

ExecutorService service;
CyclicBarrier c1 = new CyclicBarrier(2);
CyclicBarrier c2 = new CyclicBarrier(2);

public static void main(String[] args) {
    Method2CyclicBarrier m = new Method2CyclicBarrier();
    m.runPingPong();
}

public void runPingPong(){
    service = Executors.newFixedThreadPool(2);
        service.submit(() -> this.printPing(c1, c2));
        service.submit(() -> this.printPong(c1, c2));
}



public void printPing(CyclicBarrier c1, CyclicBarrier c2) {
    while(!Thread.currentThread().isInterrupted()) {
        try {
            c1.await();
            System.out.println("PING");
            c2.await();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        catch(BrokenBarrierException ex){

        }
    }
}

public void printPong(CyclicBarrier c1, CyclicBarrier c2){
    while(!Thread.currentThread().isInterrupted()) {
        try {
            c1.await();
            c2.await();
            System.out.println("PONG");
        } catch (InterruptedException ex) {
            Thread.currentThread().interrupt();
        } catch(BrokenBarrierException ex){

        }
    }
}
}

I have solved similar problem with couple of instrument. The problem I was trying to solve is Ping Pong Service. two thread one prints Ping and the other prints Pong. but They have to be SEQUENTIAL. (no double Ping or double Pong)

I will put one of the Implementation here but you can have a look other implementation (6 or 7 different way for now)
https://github.com/tugrulkarakaya/pingpong

import java.util.concurrent.*;

public class Method2CyclicBarrier {

ExecutorService service;
CyclicBarrier c1 = new CyclicBarrier(2);
CyclicBarrier c2 = new CyclicBarrier(2);

public static void main(String[] args) {
    Method2CyclicBarrier m = new Method2CyclicBarrier();
    m.runPingPong();
}

public void runPingPong(){
    service = Executors.newFixedThreadPool(2);
        service.submit(() -> this.printPing(c1, c2));
        service.submit(() -> this.printPong(c1, c2));
}



public void printPing(CyclicBarrier c1, CyclicBarrier c2) {
    while(!Thread.currentThread().isInterrupted()) {
        try {
            c1.await();
            System.out.println("PING");
            c2.await();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        catch(BrokenBarrierException ex){

        }
    }
}

public void printPong(CyclicBarrier c1, CyclicBarrier c2){
    while(!Thread.currentThread().isInterrupted()) {
        try {
            c1.await();
            c2.await();
            System.out.println("PONG");
        } catch (InterruptedException ex) {
            Thread.currentThread().interrupt();
        } catch(BrokenBarrierException ex){

        }
    }
}
}
故事灯 2024-08-19 17:37:03

是的。

如果通过一种同步方法访问该列表,则来自多个线程的并发请求将被序列化。

Yes.

If access to the list is via one synchronized method, concurrent requests from multiple threads will be serialized.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文