学习Java,使用synchronized关键字
所以我用synchronized
关键字进行测试。 这是我尝试的一个例子:
public class MyTest { static int i = 0; public static void main(String[] args) { new Thread(t1).start(); new Thread(t2).start(); } private static void countMe(String name){ i++; System.out.println("Current Counter is: " + i + ", updated by: " + name); } private static Runnable t1 = new Runnable() { public void run() { try{ for(int i=0; i<5; i++){ countMe("t1"); } } catch (Exception e){} } }; private static Runnable t2 = new Runnable() { public void run() { try{ for(int i=0; i<5; i++){ countMe("t2"); } } catch (Exception e){} } }; }
当我运行它时,从两个线程调用countMe()
方法的输出生成此输出:
Current Counter is: 1 Current Counter is: 2 Current Counter is: 4 Current Counter is: 5 Current Counter is: 6 Current Counter is: 7 Current Counter is: 3 Current Counter is: 8 Current Counter is: 9 Current Counter is: 10
当我将方法countMe()
更改为:
private synchronized static void countMe(){ i++; System.out.println("Current Counter is: " + i); }
我得到这个输出:
Current Counter is: 1 Current Counter is: 2 Current Counter is: 3 Current Counter is: 4 Current Counter is: 5 Current Counter is: 6 Current Counter is: 7 Current Counter is: 8 Current Counter is: 9 Current Counter is: 10
虽然这让我清楚地了解了synchronized
的目的,但我想知道还有其他原因,我们可以使用synchronized
。 或者我在这里做的,是我们需要使用这个synchronized
关键字的唯一原因吗?
谢谢。
编辑:我很困惑的另一件事是,在第一次输出为什么计数器在7之后变为3.对我来说似乎有点不可能,但每次尝试都会发生类似的结果,这是正常的吗?
两件事情:
首先,不可能对同一对象上的两个同步方法的调用进行交错。 当一个线程正在为对象执行同步方法时,所有其他线程都会调用同一对象的同步方法(暂停执行),直到第一个线程完成对象为止。
其次,当同步方法退出时,它会自动与同一对象的同步方法的任何后续调用建立先发生关系。 这可以保证对所有线程都可以看到对象状态的更改。
同步方法启用了一种简单的策略来防止线程干扰和内存一致性错误:如果一个对象对多个线程可见,则对该对象变量的所有读取或写入都是通过同步方法完成的。 (一个重要的例外:构造对象后无法修改的final字段,一旦构造了对象,就可以通过非同步方法安全地读取)。
来源: http : //docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html
Vulkanino对你的主要问题给出了一个很好的答案,所以我只会在7之后解决你关于3打印的问题。
3可以在7之后打印,因为在语句中实际上有比Java代码更多的字节代码。
我将扩展它。
你打电话
System.out.println("Current Counter is: " + i);
它出现在一行Java代码中,但真正发生的是创建一个字符串然后将该字符串传递给println。 println方法本身必须在实际将该行写入控制台之前进行一些处理。
从概念上讲,会发生以下情况。
String printlnString = "Current Counter is: 3" --> maybe the other thread executes here System.out.println(printlnString); --> or maybe the other thread executes here i is now equal to 7 and the console has "Current Counter is: 7" println writes "Current Counter is: 3" to console