java中的同步功能是如何工作的?

发布于 2024-11-18 07:59:17 字数 189 浏览 4 评论 0 原文

自从我开始用 Java 编程以来,我一直在想这个问题(大约一两年)。在C中,我们必须知道不同的方法才能正确避免线程之间的死锁,因此同步方法之间有更多的选择。

那么Java呢?当我们进行同步时,如何避免线程陷入死锁情况?它的内部是如何运作的?是否因为我们在比 C(或 C++)更高的级别上进行同步而避免了死锁?有没有关于java中的死锁和同步的文档?

Since I've started programming in Java I have been wondering this (about a year or two). In C, we must know the different method to correctly avoid deadlock between thread and thus there is much more choice between synchronization method.

So what about Java? When we synchronize, how does it avoid putting thread in deadlock situation? How does it work internally? Does the deadlock are avoided because we synchronized on higher level than in C ( or C++)? Any documentation about deadlock and synchronization in java?

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

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

发布评论

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

评论(7

空宴 2024-11-25 07:59:17

在底层,它在字节码级别使用两个操作码 monitorentermonitorexit,它们在 JVM 全局级别获取/释放对象引用上的锁。我强烈建议您阅读 Java虚拟机如何进行线程同步

Under the hood it is using two opcodes monitorenter and monitorexit at the byte code level which acquire/release locks on an object reference at a JVM global level. I highly recommend you read How the Java virtual machine performs thread synchronization.

在巴黎塔顶看东京樱花 2024-11-25 07:59:17

我们在多线程代码中遇到的主要问题是共享数据,我同意并发并行化进程的目的,并且“经常”发生在并行化处理期间线程需要访问以读取/写入共享数据。

java的synchronized关键字允许以下操作:

它告诉JVM在对象或同步代码片段的监视器上放置一个锁,这使其能够独占访问该部分代码或对象。

这是一个单例的例子:

public class Singleton {
    private Singleton INSTANCE;

    private Singleton() {
    }

    public Singleton getInstance() {
        if (null == INSTANCE) {
            INSTANCE = new Singleton();
        }
        return INSTANCE;
    }
}

这个单例不是线程安全,如果一个线程试图获取一个实例,而另一个线程也试图做同样的事情(竞争条件),那么可能会发生在此之前第一个线程完成了实例的创建,第二个线程已经可以访问 getInstance() 方法并创建了他自己的 Singleton 实例,这意味着在 T 时间内我们应该有两个实例Singleton(当时称为multiton)。

为了解决这个问题,我们必须同步单例的创建行为,这可以通过 INSTANCE 本身的 if 语句上方的关键字 synchronized 来完成:

public class Singleton {
    private Singleton INSTANCE;

    private Singleton() {
    }

    public Singleton getInstance() {
        synchronized (Singleton.class) {
            if (null == INSTANCE) {
                synchronized(Singleton.class) {
                   Singleton inst = new Singleton();
                   INSTANCE = inst;   
                }
            }
        }
        return INSTANCE;
    }
}

结果是第一个线程请求 Singleton 实例,并且在创建期间,JVM 将在实例的监视器上加锁,拒绝对实例的任何访问,直到线程 1 完成其请求。

也有不同的方法可以实现这一点,前面引用的书是一个很好的学习来源,javadoc也是。

The main problem(s) we meet with a multithreaded code is sharing data, and I agree with, the purpose of concurency parallizing process and it happens "ofently" that during parallalized processing that threads need accessing for read/write on shared data.

The java synchronized keyword permits the following:

It tells the JVM to put a lock on the monitor of the object or the piece of the synchronized code, which gives it exclusive access to that part of code or object.

Here's an example of a Singleton:

public class Singleton {
    private Singleton INSTANCE;

    private Singleton() {
    }

    public Singleton getInstance() {
        if (null == INSTANCE) {
            INSTANCE = new Singleton();
        }
        return INSTANCE;
    }
}

This Singleton is not thread safe, if a thread is trying to get an instance while another is also trying to do the same (race condition) it may happen that before that the thread number one finishes the creation of the instance the second has already had access to the getInstance() method and created his own instance of the Singleton which means that at a T time we should have two instances of the Singleton (called multiton at that time).

To solve this problem we have to synchronize the creational behaviour of the singleton, this may be done by the keyword synchronized above the if statement on the INSTANCE itself:

public class Singleton {
    private Singleton INSTANCE;

    private Singleton() {
    }

    public Singleton getInstance() {
        synchronized (Singleton.class) {
            if (null == INSTANCE) {
                synchronized(Singleton.class) {
                   Singleton inst = new Singleton();
                   INSTANCE = inst;   
                }
            }
        }
        return INSTANCE;
    }
}

The result is when the first thread asks the Singleton instance and during creation time, the JVM will put a lock on the monitor of the INSTANCE denying any access to the INSTANCE until thread one finished its request.

There are diffrent ways to achieve that as well, the book cited before is an excellent source of learning, javadoc also.

ぶ宁プ宁ぶ 2024-11-25 07:59:17

Java 中的同步实际上并不比 C 中的容易多少。从语法上来看,它更容易,因为对于互斥体,您所需要做的就是将方法声明为同步或使用,

synchronized(someObject)
{
   someCode();
}

而在 C/C++ 中,您可以要使用操作系统特定的函数来使用互斥锁,或者您必须使用 Boost 库。

但关于死锁的陷阱与任何语言基本上都是相同的。

Synchronization isn't really that much easier in Java than in C. Syntactically it's easier, because all you need to do for a mutex is declare a method as synchronized or use

synchronized(someObject)
{
   someCode();
}

Whereas in C/C++, you have to use operating-system-specific functions to use a mutex, or you have to use the Boost library.

But the pitfalls about deadlock are all basically the same as in any language.

书信已泛黄 2024-11-25 07:59:17

简短回答:

  1. 同步方法和lock块使用监视器来锁定锁定对象的信号量在方法或块的持续时间内。

  2. Java 语言本身并不能防止死锁。作为程序员,您需要确保以正确的顺序锁定/解锁对象以防止争用。

Short answers:

  1. synchronized methods and lock blocks use a monitor that locks the semaphore of the locked object for the duration of the method or block.

  2. The Java language itself does not prevent deadlocks. That's up to you as the programmer to insure that objects are locked/unlocked in the correct order to prevent contention.

深空失忆 2024-11-25 07:59:17

您还必须处理 Java 中的死锁。产生死锁的最简单方法是让一个线程在 A 上运行一个同步块,然后在 B 上运行另一个同步块,而另一个线程在 B 上执行一个同步块,然后在 A 上运行一个同步块

。阅读 有关并发的 Java 教程。 如果您想继续学习,请阅读Java 并发实践

You also have to take care of deadlocks in Java. The easiest way to get a deadlock is to make one thread run a block synchronized on A, and then another block synchronized on B, while another thread executes a block synchronized on B, and then a block synchronized on A.

Read the Java tutorial about concurrency. And if you want to keep learning, read Java concurrency in practice.

时光清浅 2024-11-25 07:59:17

您是否尝试过 google(Java 死锁)?第一个结果是这样的: http://download.oracle.com/javase/ tutorial/essential/concurrency/deadlock.html

在这里您可以看到,使用synchronized死锁仍然会发生,因为同步的设计初衷并不是为了防止死锁。

Did you try google (Java Deadlock)? First result is this: http://download.oracle.com/javase/tutorial/essential/concurrency/deadlock.html

There you can see that with synchronized deadlocks still occur, since synchronization is not designed to prevent those in the first place.

咋地 2024-11-25 07:59:17

我在上面看到了 Singleton 的一些问题。我认为这个类永远不会被创建。请考虑下面的代码。

public class Singleton {
     private static Singleton INSTANCE;
     private Singleton() {     }
     public static Singleton getInstance() {
         synchronized (Singleton.class) {
             if (null == INSTANCE) {
                 synchronized(Singleton.class) {
                    Singleton inst = new Singleton();
                    INSTANCE = inst;
                    }
             }
         }
         return INSTANCE;
     }
 } 

I see some issue with Singleton above. I think that class will never be created. Please consider below code.

public class Singleton {
     private static Singleton INSTANCE;
     private Singleton() {     }
     public static Singleton getInstance() {
         synchronized (Singleton.class) {
             if (null == INSTANCE) {
                 synchronized(Singleton.class) {
                    Singleton inst = new Singleton();
                    INSTANCE = inst;
                    }
             }
         }
         return INSTANCE;
     }
 } 
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文