【问题标题】:How to start concurrent threads that acquire a file lock and wait on each other如何启动获取文件锁并相互等待的并发线程
【发布时间】:2012-09-27 08:21:27
【问题描述】:

我正在学习FileLock 课程。我想做的是启动三个Threads,它们将同时运行并访问一个文件。当文件被一个线程锁定时,我希望其他两个线程在释放锁时等待轮到它们。但是,当我在下面运行我的代码时,线程甚至不会同时启动——它们一个接一个地启动,只要它们的每个 run() 方法完成。我不明白。

public class Main {

    public static void main(String[] args) {
        Main m = new Main();
        SomeThread t1 = m.new SomeThread("t1");
        SomeThread t2 = m.new SomeThread("t2");
        SomeThread t3 = m.new SomeThread("t3");
        t1.run();
        t3.run();
        t2.run();
    }

    class SomeThread implements Runnable {
        String name;

        public SomeThread(String s) {
            name = s;
        }

        @Override
        public void run() {
            System.out.println(name + " started!");
            OtherClass.access(name);
        }
    }

    static class OtherClass {
        static File file = new File("testfile.txt");

        public static void access(String name) {
            FileChannel channel = null;
            FileLock lock = null;
            try {
                channel = new RandomAccessFile(file, "rw").getChannel();
                lock = channel.lock();
                System.out.println("locked by " + name);
                Thread.sleep(3000);
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } finally {
                if (lock != null) {
                    try {
                        lock.release();
                        System.out.println("released by " + name);
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                if (channel != null) {
                    try {
                        channel.close();
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}

如何实现我想要达到的场景?为什么他们不同时开始?我认为lock() 方法只会让访问同一文件的其他线程等到锁被释放。

【问题讨论】:

    标签: java multithreading file-io thread-safety file-locking


    【解决方案1】:

    线程以Thread.start 开头,而不是Thread.runrun 只会在主线程上按顺序调用run 方法。

    实际上你甚至没有创建线程:

    public static void main(String[] args) {
        Main m = new Main();
        Thread t1 = new Thread(m.new SomeThread("t1"));
        Thread t2 = new Thread(m.new SomeThread("t2"));
        Thread t3 = new Thread(m.new SomeThread("t3"));
        t1.start();
        t2.start();
        t3.start();
    }
    

    【讨论】:

    • 啊,你的意思是在Thread 对象中传递Runnable
    • 只是为了记录,这将生成一个OverlappingFileLockException
    • @mattquiros:这意味着我猜OtherClass 也有问题,但现在至少你有并发线程。
    • @mattquiros:FileLock 的文档说:File locks are held on behalf of the entire Java virtual machine. They are not suitable for controlling access to a file by multiple threads within the same virtual machine. 你为什么不直接使用普通锁呢?
    【解决方案2】:

    算了。它行不通。文件锁代表整个进程,而不是单个线程。

    【讨论】:

    • 我猜他可以用普通锁代替。
    • 有趣。现在不知道如何让AsyncTasks在Android中读写同一个文件坐标。
    • @Tudor 什么是普通锁?我必须自己写的东西?
    • @mattquiros:你只需要ReentrantLock类:docs.oracle.com/javase/6/docs/api/java/util/concurrent/locks/…
    • @mattquiros 它不应该那么有趣,也不应该有那么大的惊喜。 Javadoc 中几乎完全按照这些术语进行了说明。
    猜你喜欢
    • 2012-06-13
    • 1970-01-01
    • 2012-10-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多