[英]A Java beginner question regarding multi-threading
多年不使用Java之后,我正在提高自己的Java技能。 最近,我一直在阅读有关多线程的一章,其中提到:
“但是,如果您有一个访问静态字段的非静态方法?或者是访问一个非静态字段(使用实例)的静态方法?在这些情况下,事情很快就会变得混乱起来,如果您有静态方法访问非静态字段,并且同步了该方法,则您将获得对Class对象的锁定,但是如果还有另一个方法也可以访问该对象,该怎么办?非静态字段,这一次使用非静态方法吗?它可能在当前实例(this)上同步 。 请记住,静态同步方法和非静态同步方法不会互相阻塞,它们可以在以下位置运行同时。 ”
为了学习起见,我一直在尝试编写一个示例,其中上面的片段中引用了一种方案:该程序中的静态同步方法修改了一个非静态字段,该方法同时运行一个非静态字段。同步方法。
因此,到目前为止,我还没有成功做到这一点。 感谢您的帮助。 谢谢!
以下是我完成的代码示例。 但是,正如预期的那样,由于线程已同步,因此它们不会同时运行。 我只是想看看书上提到的一个例子,所以我会知道不该做什么。
class code147_class1{
int num1 = 111;
static int num2 = 222;
}//code147_class1
public class code147 implements Runnable {
code147_class1 z = new code147_class1();
public static void main (String args[]){
System.out.println("Program has started...");
System.out.println("The value of the instance variable is:"+new code147_class1().num1);
System.out.println("The value of the static variable is:"+code147_class1.num2);
code147 cd1 = new code147();
Thread thread1 = new Thread(cd1);
Thread thread2 = new Thread(cd1);
thread1.start();
thread2.start();
}//main
public void run(){
System.out.println("Thread has started for:"+Thread.currentThread().getId());
try{
subtract_instance_var(z);
Thread.sleep(100);
code147.static_subtract_instance_var(z);
}
catch(Exception ex){
}
}//run
public synchronized void subtract_instance_var(code147_class1 x){
if(x.num1 ==111){
try{
Thread.sleep(100);
}
catch(Exception ex){
}
x.num1 = x.num1 - 11;
System.out.println("Value is subtracted at thread:"+Thread.currentThread().getId());
}//if
System.out.println("The value of instance variable at the end for thread: "+Thread.currentThread().getId()+" is "+x.num1);
}//subtract_instance_var
public synchronized static void static_subtract_instance_var(code147_class1 x){
if (x.num1==111){
try{
Thread.sleep(100);
}
catch(InterruptedException ex){
}//catch
x.num1 = x.num1 -11;
System.out.println("Value is subtracted at thread:"+Thread.currentThread().getId());
}//if
System.out.println("STATIC The value of instance variable at the end for thread: "+Thread.currentThread().getId()+" is "+x.num1);
}//stati_subtract_var
}//class
运行代码后,我期望实例变量的值为89。但是该程序的结果为100。
您得到的结果100是正确的。 线程1和线程2将同时运行。 因为“ subtract_instance_var”方法是同步的,所以一个线程将使变量100。然后该线程将进入睡眠状态。 随着锁释放,其他线程可以执行“ subtract_instance_var”。 但是,由于“ x.num1 == 111”条件失败,将不会发生任何事情。 休眠后,当两个线程都尝试执行“ static_subtract_instance_var”方法时,“ x.num1 == 111”的条件仍然失败。 因此变量值仍为100。
您的示例代码不会同时执行静态减法和实例减法。 因此,没有线程安全。
另外,如果原始值为111,则您的代码仅减去11。因此,结果为100。
这是一个备用的main,它将同时执行substract和static_substract。
public static void main(String args[]) {
System.out.println("Program has started...");
System.out.println("The value of the instance variable is:" + new Code147_class1().num1);
System.out.println("The value of the static variable is:" + Code147_class1.num2);
Code147 cd1 = new Code147();
Thread thread1 = new Thread(() -> {
IntStream.range(0, 5).forEach(i->{
cd1.subtract_instance_var(cd1.z);
});
}, "instance thread");
Thread thread2 = new Thread(() -> {
IntStream.range(0, 5).forEach(i->{
static_subtract_instance_var(cd1.z);
});
}, "static thread");
thread1.start();
thread2.start();
}// main
请注意,在此代码中,两个线程从初始111减去每个11,共5次。剩下的应该是1。由于线程安全,它不一定总是这样。
import java.util.stream.IntStream;
class Code147_class1 {
int num1 = 111;
}// Code147_OK_class1
public class Code147 {
Code147_OK_class1 z = new Code147_OK_class1();
public static void main(String args[]) {
System.out.println("Program has started...");
System.out.println("The value of the instance variable is:" + new Code147_OK_class1().num1);
Code147 cd1 = new Code147();
Thread thread1 = new Thread(() -> {
IntStream.range(0, 5).forEach(i -> {
System.out.println("\tInstance Substract 11 #" + (i + 1));
cd1.subtract_instance_var(cd1.z);
});
}, "instance thread");
Thread thread2 = new Thread(() -> {
IntStream.range(0, 5).forEach(i -> {
System.out.println("\tStatic Substract 11 #" + (i + 1));
static_subtract_instance_var(cd1.z);
});
}, "static thread");
thread1.start();
thread2.start();
}// main
public synchronized void subtract_instance_var(Code147_OK_class1 x) {
// if (x.num1 == 111) {
try {
Thread.sleep(100);
} catch (Exception ex) {
}
x.num1 = x.num1 - 11;
System.out.println("Value is subtracted at thread T" + Thread.currentThread().getId());
// } // if
System.out.println("The value of instance variable at the end for thread T" + Thread.currentThread().getId()
+ " is " + x.num1);
}// subtract_instance_var
public synchronized static void static_subtract_instance_var(Code147_OK_class1 x) {
// if (x.num1 == 111) {
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
} // catch
x.num1 = x.num1 - 11;
System.out.println("STATIC Value is subtracted at thread T" + Thread.currentThread().getId());
// } // if
System.out.println("STATIC The value of instance variable at the end for thread T"
+ Thread.currentThread().getId() + " is " + x.num1);
}// stati_subtract_var
}// class
示例输出
Program has started... The value of the instance variable is:111 Instance Substract 11 #1 Static Substract 11 #1 STATIC Value is subtracted at thread T11 STATIC The value of instance variable at the end for thread T11 is 89 Static Substract 11 #2 Value is subtracted at thread T10 The value of instance variable at the end for thread T10 is 89 Instance Substract 11 #2 Value is subtracted at thread T10 STATIC Value is subtracted at thread T11 The value of instance variable at the end for thread T10 is 67 Instance Substract 11 #3 STATIC The value of instance variable at the end for thread T11 is 67 Static Substract 11 #3 STATIC Value is subtracted at thread T11 Value is subtracted at thread T10 The value of instance variable at the end for thread T10 is 45 Instance Substract 11 #4 STATIC The value of instance variable at the end for thread T11 is 45 Static Substract 11 #4 Value is subtracted at thread T10 STATIC Value is subtracted at thread T11 The value of instance variable at the end for thread T10 is 23 Instance Substract 11 #5 STATIC The value of instance variable at the end for thread T11 is 23 Static Substract 11 #5 Value is subtracted at thread T10 The value of instance variable at the end for thread T10 is 12 STATIC Value is subtracted at thread T11 STATIC The value of instance variable at the end for thread T11 is 12
请注意,最后一个值是12,而不是1 ...
您可以通过在同一监视器上进行同步来确保程序线程的安全,在本例中为z:
import java.util.stream.IntStream;
class Code147_OK_class1 {
int num1 = 111;
}// Code147_OK_class1
public class Code148_OK {
Code147_class1 z = new Code147_class1();
public static void main(String args[]) {
System.out.println("Program has started...");
System.out.println("The value of the instance variable is:" + new Code147_class1().num1);
Code148_OK cd1 = new Code148_OK();
Thread thread1 = new Thread(() -> {
IntStream.range(0, 5).forEach(i -> {
System.out.println("\tInstance Substract 11 #" + (i + 1));
cd1.subtract_instance_var(cd1.z);
});
}, "instance thread");
Thread thread2 = new Thread(() -> {
IntStream.range(0, 5).forEach(i -> {
System.out.println("\tStatic Substract 11 #" + (i + 1));
static_subtract_instance_var(cd1.z);
});
}, "static thread");
thread1.start();
thread2.start();
}// main
public /* synchronized */ void subtract_instance_var(Code147_class1 x) {
synchronized (x) {
// if (x.num1 == 111) {
try {
Thread.sleep(100);
} catch (Exception ex) {
}
x.num1 = x.num1 - 11;
System.out.println("Value is subtracted at thread T" + Thread.currentThread().getId());
// } // if
System.out.println("The value of instance variable at the end for thread T" + Thread.currentThread().getId()
+ " is " + x.num1);
}
}// subtract_instance_var
public /* synchronized */ static void static_subtract_instance_var(Code147_class1 x) {
synchronized (x) {
// if (x.num1 == 111) {
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
} // catch
x.num1 = x.num1 - 11;
System.out.println("STATIC Value is subtracted at thread T" + Thread.currentThread().getId());
// } // if
System.out.println("STATIC The value of instance variable at the end for thread T"
+ Thread.currentThread().getId() + " is " + x.num1);
}
}// stati_subtract_var
}// class
输出量
Program has started... The value of the instance variable is:111 Instance Substract 11 #1 Static Substract 11 #1 Value is subtracted at thread T10 The value of instance variable at the end for thread T10 is 100 Instance Substract 11 #2 STATIC Value is subtracted at thread T11 STATIC The value of instance variable at the end for thread T11 is 89 Static Substract 11 #2 Value is subtracted at thread T10 The value of instance variable at the end for thread T10 is 78 Instance Substract 11 #3 STATIC Value is subtracted at thread T11 STATIC The value of instance variable at the end for thread T11 is 67 Static Substract 11 #3 Value is subtracted at thread T10 The value of instance variable at the end for thread T10 is 56 Instance Substract 11 #4 STATIC Value is subtracted at thread T11 STATIC The value of instance variable at the end for thread T11 is 45 Static Substract 11 #4 Value is subtracted at thread T10 The value of instance variable at the end for thread T10 is 34 Instance Substract 11 #5 STATIC Value is subtracted at thread T11 STATIC The value of instance variable at the end for thread T11 is 23 Static Substract 11 #5 Value is subtracted at thread T10 The value of instance variable at the end for thread T10 is 12 STATIC Value is subtracted at thread T11 STATIC The value of instance variable at the end for thread T11 is 1
告诉我如果Java 8 lambda的东西不清楚,我将用“经典的” Runnables和循环将其重写。
HTH!
通过@Highbrainer的输入,我设法使一个程序运行2个线程,其中1个运行同步实例方法,另一个运行静态方法。 两者都修改实例字段。 正如书中所建议的那样,为避免此类问题,我们应该始终从实例方法修改实例字段,并从as静态方法修改静态字段。 我刚刚修改了程序,将静态方法更改为实例方法。
class code148_class1{
int num1 = 111;
}//code148_class1
public class code148 implements Runnable {
static code148_class1 z = new code148_class1();
public static void main (String args[]){
System.out.println("Program has started...");
System.out.println("The value of the instance variable is:"+z.num1);
code148 cd1 = new code148();
Thread thread1 = new Thread(
()->{
cd1.subtract_instance_var(z);
}
);
Thread thread2 = new Thread(
()->{
cd1.NONstatic_subtract_instance_var(z);
}
);
thread1.start();
thread2.start();
}//main
public void run(){
System.out.println("Thread has started for:"+Thread.currentThread().getId());
// try{
// subtract_instance_var(z);
// Thread.sleep(100);
// code148.static_subtract_instance_var(z);
// }
// catch(Exception ex){
//
// }
}//run
public synchronized void subtract_instance_var(code148_class1 x){
if(x.num1 ==111){
try{
Thread.sleep(100);
}
catch(Exception ex){
}
x.num1 = x.num1 - 11;
System.out.println("Value is subtracted at thread:"+Thread.currentThread().getId());
}//if
System.out.println("The value of instance variable at the end for thread: "+Thread.currentThread().getId()+" is "+x.num1);
}//subtract_instance_var
public synchronized void NONstatic_subtract_instance_var(code148_class1 x){
if (x.num1==111){
try{
Thread.sleep(100);
}
catch(InterruptedException ex){
}//catch
x.num1 = x.num1 -11;
System.out.println("Value is subtracted at thread:"+Thread.currentThread().getId());
}//if
System.out.println("STATIC The value of instance variable at the end for thread: "+Thread.currentThread().getId()+" is "+x.num1);
}//stati_subtract_var
}//class
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.