在java中,不同的线程可以同时访问同一对象的不同独立方法吗?
假设我们有两个线程,一个对象有两个方法。 线程1使用method1。 当线程1使用的method1仍在运行时,线程2可以使用method2吗 所有这些都假设对象不是在考虑多线程的情况下构建的(没有同步或类似),并且这些方法不访问相同的变量 该代码表明有可能:在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
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
关键字以及线程安全类,例如hasAtomicInteger
,以确保正确访问共享变量和关键部分。代码的问题在于两种方法firstmethod
和secondmethod
并不像您想象的那样“独立”,因为两者都有callCount++
这可能会创建错误,因为两个线程都在更新该变量。您需要使用AtomicInteger
而不是int,这样代码就可以工作了
编辑:
通常,默认情况下不会启用同步机制(“自动阻塞”),因为这些操作成本高昂,并且会降低程序的速度。这就是为什么Java提供了
synchronized
关键字以及线程安全类,例如hasAtomicInteger
,以确保正确访问共享变量和关键部分。您是对的,确实存在共享变量,这可能会导致竞争条件,但这让我更难理解,因为代码(除了callCount情况)的工作原理是启动第一个方法,启动第二个方法并结束它,然后结束第一个方法。我一直认为会有一些自动阻塞(无法访问一个方法,同时运行来自同一对象的另一个方法),但没有?这意味着任何线程都可以在任何时间执行任何对象的任何方法?@harbun No没有您描述的“自动阻塞”。这就是为什么像AtomicInteger
这样的类存在“自动阻塞”,通常通过锁定或synchronized
关键字来实现,这在默认情况下是不存在的,因为这类操作很昂贵,并且会减慢程序的速度。这为我清除了它,谢谢!你能在回答中添加最后两条注释吗?你是对的,确实存在一个共享变量,这可能会导致竞争条件,但这让我更难以理解,因为代码在启动第一个方法、启动第二个方法和结束它的意义上起作用(除了调用计数情况),然后结束第一个方法。我一直认为会有一些自动阻塞(无法访问一个方法,同时运行来自同一对象的另一个方法),但没有?这意味着任何线程都可以在任何时间执行任何对象的任何方法?@harbun No没有您描述的“自动阻塞”。这就是为什么像AtomicInteger
这样的类存在“自动阻塞”,通常通过锁定或synchronized
关键字来实现,这在默认情况下是不存在的,因为这类操作很昂贵,并且会减慢程序的速度。这为我清除了它,谢谢!你能在你的回答中加上最后两条评论吗?