在java中,不同的线程可以同时访问同一对象的不同独立方法吗?

在java中,不同的线程可以同时访问同一对象的不同独立方法吗?,java,multithreading,Java,Multithreading,假设我们有两个线程,一个对象有两个方法。 线程1使用method1。 当线程1使用的method1仍在运行时,线程2可以使用method2吗 所有这些都假设对象不是在考虑多线程的情况下构建的(没有同步或类似),并且这些方法不访问相同的变量 该代码表明有可能: import java.io.IOException; import java.util.logging.Level; import java.util.logging.Logger; public class multithreadac

假设我们有两个线程,一个对象有两个方法。 线程1使用method1。 当线程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();
            }
        }
    }
修改源代码


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

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

这可能会创建错误,因为两个线程都在更新该变量。您需要使用
AtomicInteger
而不是int,这样代码就可以工作了

编辑:
通常,默认情况下不会启用同步机制(“自动阻塞”),因为这些操作成本高昂,并且会降低程序的速度。这就是为什么Java提供了
synchronized
关键字以及线程安全类,例如has
AtomicInteger
,以确保正确访问共享变量和关键部分。

代码的问题在于两种方法
firstmethod
secondmethod
并不像您想象的那样“独立”,因为两者都有
callCount++

这可能会创建错误,因为两个线程都在更新该变量。您需要使用
AtomicInteger
而不是int,这样代码就可以工作了

编辑:
通常,默认情况下不会启用同步机制(“自动阻塞”),因为这些操作成本高昂,并且会降低程序的速度。这就是为什么Java提供了
synchronized
关键字以及线程安全类,例如has
AtomicInteger
,以确保正确访问共享变量和关键部分。

您是对的,确实存在共享变量,这可能会导致竞争条件,但这让我更难理解,因为代码(除了callCount情况)的工作原理是启动第一个方法,启动第二个方法并结束它,然后结束第一个方法。我一直认为会有一些自动阻塞(无法访问一个方法,同时运行来自同一对象的另一个方法),但没有?这意味着任何线程都可以在任何时间执行任何对象的任何方法?@harbun No没有您描述的“自动阻塞”。这就是为什么像
AtomicInteger
这样的类存在“自动阻塞”,通常通过锁定或
synchronized
关键字来实现,这在默认情况下是不存在的,因为这类操作很昂贵,并且会减慢程序的速度。这为我清除了它,谢谢!你能在回答中添加最后两条注释吗?你是对的,确实存在一个共享变量,这可能会导致竞争条件,但这让我更难以理解,因为代码在启动第一个方法、启动第二个方法和结束它的意义上起作用(除了调用计数情况),然后结束第一个方法。我一直认为会有一些自动阻塞(无法访问一个方法,同时运行来自同一对象的另一个方法),但没有?这意味着任何线程都可以在任何时间执行任何对象的任何方法?@harbun No没有您描述的“自动阻塞”。这就是为什么像
AtomicInteger
这样的类存在“自动阻塞”,通常通过锁定或
synchronized
关键字来实现,这在默认情况下是不存在的,因为这类操作很昂贵,并且会减慢程序的速度。这为我清除了它,谢谢!你能在你的回答中加上最后两条评论吗?