当使用静态对象锁不起作用时?
When using static object lock doesn't work?
我是并发的新手,我想了解同步块:
public static int count1 = 0;
public static Object lock1 = new Object();
public static void add(){
synchronized (lock1) {
count1++;
}
}
我的问题是 lock1,它不起作用,当该方法开始打印颜色时,它随机打印它们,所以我认为问题出在同步块中,因为我看了一些关于这个的教程,所有他们说锁定对象必须是静态的,所以不会发生干扰,但我在这里没有看到,为什么?
这是打印每根线的颜色的方法:
public static void compute(){
String color = null;
switch (Thread.currentThread().getName()) {
case "First Count Down":
color = TextColors.ANSI_YELLOW;
break;
case "Second Count Down":
color = TextColors.ANSI_MAGENTA;
break;
}
for (int i=0;i<100;i++) {
System.out.println(color + Thread.currentThread().getName() + "is Running");
//add();
add();
}
}
这是线程:
public static void main(String[] args) {
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
compute();
}
});
t1.setName("First Count Down");
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
compute();
}
});
t2.setName("Second Count Down");
t1.start();
t2.start();
try{
t1.join();
t2.join();
}catch (InterruptedException io){
io.printStackTrace();
}
System.out.println("Count1 = " + count1 + " Count2 = " + count2);
}
对不起,如果我的英语不好,我不是母语人士,提前致谢
首先,我想我现在明白你的问题了。您正在尝试在不干扰其他线程的情况下打印出您的行。
要实现这一点,您必须 "protect" 打印出一行的代码部分,而不是同时从另一个线程打印出另一行。
可以通过同步这些代码行来完成保护。
您当前只同步该计数器的添加项。
你的锁(你锁定的对象,新对象()的唯一实例)是静态的,你没有在你的代码中改变它,所以它必须有效。
public static Object lock1 = new Object();
您可以将变量设为 final 以使其不可变,但目前这不是问题所在。不过我会推荐。
锁意味着,如果任何其他线程登陆(执行)同一行代码(同步块的开头),它们将不会执行,直到阻塞线程放弃其锁。只有当他们持有并要求完全相同的锁时,这才是正确的。由于您只使用完全相同的 new Object() 实例,因此您的锁应该没问题。
目前您的代码是这样构建的,即 add() 方法基本上会等待其中一个线程计数为 1。
如果您想更改它以便单独打印行,请尝试像这样同步 "line printing block":
synchronized (lock1) {
System.out.println(color + Thread.currentThread().getName() + "is Running");
add();
}
并且让计数不同步
private static void add(){
count1++;
}
这可行,但大多数情况下您不想让 add() 方法不同步。它可以从其他线程执行,谁知道呢。但对于您的情况,这些更改会有所帮助。
我是并发的新手,我想了解同步块:
public static int count1 = 0;
public static Object lock1 = new Object();
public static void add(){
synchronized (lock1) {
count1++;
}
}
我的问题是 lock1,它不起作用,当该方法开始打印颜色时,它随机打印它们,所以我认为问题出在同步块中,因为我看了一些关于这个的教程,所有他们说锁定对象必须是静态的,所以不会发生干扰,但我在这里没有看到,为什么?
这是打印每根线的颜色的方法:
public static void compute(){
String color = null;
switch (Thread.currentThread().getName()) {
case "First Count Down":
color = TextColors.ANSI_YELLOW;
break;
case "Second Count Down":
color = TextColors.ANSI_MAGENTA;
break;
}
for (int i=0;i<100;i++) {
System.out.println(color + Thread.currentThread().getName() + "is Running");
//add();
add();
}
}
这是线程:
public static void main(String[] args) {
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
compute();
}
});
t1.setName("First Count Down");
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
compute();
}
});
t2.setName("Second Count Down");
t1.start();
t2.start();
try{
t1.join();
t2.join();
}catch (InterruptedException io){
io.printStackTrace();
}
System.out.println("Count1 = " + count1 + " Count2 = " + count2);
}
对不起,如果我的英语不好,我不是母语人士,提前致谢
首先,我想我现在明白你的问题了。您正在尝试在不干扰其他线程的情况下打印出您的行。
要实现这一点,您必须 "protect" 打印出一行的代码部分,而不是同时从另一个线程打印出另一行。
可以通过同步这些代码行来完成保护。
您当前只同步该计数器的添加项。
你的锁(你锁定的对象,新对象()的唯一实例)是静态的,你没有在你的代码中改变它,所以它必须有效。
public static Object lock1 = new Object();
您可以将变量设为 final 以使其不可变,但目前这不是问题所在。不过我会推荐。
锁意味着,如果任何其他线程登陆(执行)同一行代码(同步块的开头),它们将不会执行,直到阻塞线程放弃其锁。只有当他们持有并要求完全相同的锁时,这才是正确的。由于您只使用完全相同的 new Object() 实例,因此您的锁应该没问题。
目前您的代码是这样构建的,即 add() 方法基本上会等待其中一个线程计数为 1。
如果您想更改它以便单独打印行,请尝试像这样同步 "line printing block":
synchronized (lock1) {
System.out.println(color + Thread.currentThread().getName() + "is Running");
add();
}
并且让计数不同步
private static void add(){
count1++;
}
这可行,但大多数情况下您不想让 add() 方法不同步。它可以从其他线程执行,谁知道呢。但对于您的情况,这些更改会有所帮助。