【问题标题】:Can different threads access different independent methods of the same object at the same time in java?java中不同线程可以同时访问同一个对象的不同独立方法吗?
【发布时间】:2018-11-19 01:06:18
【问题描述】:

假设我们有 2 个线程,一个对象有 2 个方法。 线程 1 使用方法 1。 线程1使用的method1还在运行时,线程2可以使用method2吗?

所有这一切都假设对象在构建时没有考虑到多线程(没有同步或类似),并且方法不访问相同的变量。

这段代码表明这是可能的:

import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;

public class multithreadaccess {

    /**
     * @param args
     *            the command line arguments
     */
    public static void main(String[] args) throws IOException {
        TestClass tc = new TestClass();

        // invokes not sync method
        FirstThreadRunnable ftr = new FirstThreadRunnable(tc);
        Thread t1 = new Thread(ftr);

        // invokes the sync method
        SecondThreadRunnable str = new SecondThreadRunnable(tc);
        Thread t2 = new Thread(str);

        t1.start();
        t2.start();

        System.in.read();
    }


    public static class TestClass {

        private int callCount = 0;

        public void secondmethod() {
            System.out.println("second method activated! Call number:" + " [" + callCount++ + "] from thread: "
                    + Thread.currentThread().getId());
        }

        public void firstmethod() throws InterruptedException {
            // Test with the sleep
            System.out.println("starting first slow method from thread: " + Thread.currentThread().getId());
            Thread.sleep(1000); // hold the monitor for 5sec
            System.out.println("stopping first slow method! Call number:" + " [" + callCount++ + "] from thread: "
                    + Thread.currentThread().getId());

            // Test with spinning
            /*
             * System.out.println("MAKE IT SPIN! from thread: " +
             * Thread.currentThread().getId()); boolean spin = true;
             * while(spin){
             * 
             * } System.out.println("IT STOPPED SPINNING! from thread: " +
             * Thread.currentThread().getId()); }
             */
        }
    }

        // invokes the not sync method
        public static class FirstThreadRunnable implements Runnable {
            TestClass tester = null;

            public FirstThreadRunnable(TestClass tester) {
                this.tester = tester;
            }

            @Override
            public void run() {
                try {
                    tester.firstmethod();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

            }
        }

        // invokes the sync method
        public static class SecondThreadRunnable implements Runnable {

            TestClass tester = null;

            public SecondThreadRunnable(TestClass tester) {
                this.tester = tester;
            }

            @Override
            public void run() {
                tester.secondmethod();
            }
        }
    }

来自here的修改代码

不过,我不明白这怎么可能。我一直认为一个对象是线性代码。但这表明线性只是方法中的代码(只要多个方法不使用变量)?

【问题讨论】:

    标签: java multithreading


    【解决方案1】:

    您的代码的问题是firstmethodsecondmethod 两种方法并不像您想象的那样“独立”,因为它们都有callCount++

    这可能会创建race condition,因为两个线程都在更新该变量。您需要使用AtomicInteger 而不是int,然后代码才能工作。

    编辑: 一般来说,默认情况下不启用同步机制(“自动阻塞”),因为这些操作代价高昂并且会减慢程序的速度。这就是为什么 Java 提供了 synchronized 关键字以及诸如 AtomicInteger 之类的线程安全类来确保正确访问共享变量和临界区的原因。

    【讨论】:

    • 你是对的,确实存在一个共享变量,这可能会导致竞争条件,但这让我更难以理解,因为代码在某种意义上有效(除了 callCount 情况)它启动第一个方法,启动第二个方法并结束它,然后结束第一个方法。我一直认为会有一些自动阻塞(无法访问一种方法,而来自同一个对象的另一种方法运行)但没有?这意味着任何线程都可以随时执行任何对象的任何方法?
    • @harbun 不,正如您所描述的那样,没有“自动阻止”。这正是为什么像AtomicInteger 这样的类存在
    • "自动阻塞" ,通常通过锁定或synchronized关键字实现,默认情况下不这样做,因为这种操作很昂贵并且会减慢程序的速度。
    • 这对我来说很清楚,谢谢!您能否将最后两个 cmets 添加到您的答案中?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-19
    相关资源
    最近更新 更多