繁体   English   中英

仅在访问相同对象的相同方法时锁定线程

[英]Lock threads only if access same method of the same object

我有一个具有多线程项目通用方法的对象。 一些方法是同步的。 我的问题是,当一个线程访问同步方法而另一个线程访问另一个同步方法时。 这将使其中一个线程等待另一个线程。 我只想在访问相同的同步方法时锁定线程,但是我不知道如何。 我发现最近关键字已同步。

这是我的方法之一。

public synchronized static void writeError(Exception err){

    String time = longDate();//here will get personalized current date
                             //longDate is not synchronized.

    try {

        FileWriter  path = new FileWriter("ERROR - " + time + ".txt",true);

        err.printStackTrace(new PrintWriter(path));

        path.flush();

    } catch (IOException e) {}

}

对这种方法有什么想法吗?

因此, synchronized始终需要对象进行操作。 共享同一对象的所有synchronized块都是互斥的 (即,一次只能有一个线程进入该块)。 synchronized放在方法声明中是简便的方法,例如,实例方法等于synchronized(this)而静态方法等于synchronized(Foo.class) (其中Foo是包含静态方法的类)。

知道了这一点,您可以轻松地创建多个要同步的对象,控制哪些方法可以同时运行,哪些方法不能同时运行。

允许方法3与方法1或方法2同时运行的示例类,但方法1和方法2是互斥的。 另外,一次只能有一个线程运行每种方法。

public class Foo {
    private final static Object lock1 = new Object();
    private final static Object lock2 = new Object();

    public static void method1() {
        synchronized(lock1) {
            ...
        }
    }

    public static void method2() {
        synchronized(lock1) {
            ...
        }
    }

    public static void method3() {
        synchronized(lock2) {
            ...
        }
    }
}

也要注意静态与非静态。 这里的方法是静态的,锁是静态的,所以一切都很好。 如果方法是非静态的,则也将阻止在其他对象上调用方法,这可能不是您想要的。 在这种情况下,将锁设为非静态将使每个Foo实例如前所述工作,但对于foo1.method1()foo2.method2()而言,不会进行锁定,因为它们不会在同一对象。

正如Shubham Kadlag的答案所表明的, synchronized并不是Java唯一的并发工具。 java.util.concurrent.locks包具有用于锁定的类(而synchronized是一种内置机制)。 例如, ReentrantReadWriteLock允许您处理多个线程可以同时执行某项操作(读取),但是一次只允许一个线程进行修改操作(写入)的情况。 它们还允许您给锁定超时,而synchronized将快乐地永远等待(不是通常需要tryLock() ,因为如果遇到死锁,这是编程错误)。

然后,您意识到手动锁定无论如何都是块,然后发现java.util.concurrent有许多类可以将锁定隐藏起来,并提供各种高级功能。

正如Kamayan所提到的,对象上的同步将满足您的需求。

此外,如果您遇到性能问题或线程数量很多,则可以申请锁。

请参阅https://dzone.com/articles/synchronized-vs-lock

如以上文章所述,对于访问锁的少量线程(<4),同步是最好的选择;对于访问相同锁的大量线程,锁可能是最好的选择。

您可以参考http://winterbe.com/posts/2015/04/30/java8-concurrency-tutorial-synchronized-locks-examples/了解不同的锁示例。

为如下所示的所有方法创建一个单独的锁。

private static ReentrantLock writeErrorlock = new ReentrantLock();

        public static void writeError(Exception err){
            writeErrorlock.lock();
            String time = longDate();//here will get personalized current date
                                     //longDate is not synchronized.

            try {

                FileWriter  path = new FileWriter("ERROR - " + time + ".txt",true);

                err.printStackTrace(new PrintWriter(path));

                path.flush();

            } catch (IOException e) {

            }
            finally {
                writeErrorlock.unlock();
            }

        }

暂无
暂无

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM