这个练习直接来自SCJP,由凯西·塞拉和伯特·贝茨完成
同步代码块
在这个练习中,我们将尝试同步一个代码块。在该代码块中,我们将获得对象的锁,以便其他线程在代码块执行时无法html" target="_blank">修改它。我们将创建三个线程,它们都将尝试操作同一对象。每个线程将输出一个字母100次,然后将该字母递增一次。我们将使用的对象是StringBuffer。
我们可以在一个String对象上进行同步,但是字符串一旦创建就不能被修改,所以我们不能在不生成一个新的String对象的情况下增加字母。最终的输出应该有100个A、100个B和100个C,都在不间断的行中。
我已经为上面的练习写了下面的类(而不是100,我正在打印10个字符)
class MySyncBlockTest extends Thread {
StringBuffer sb;
MySyncBlockTest(StringBuffer sb) {
this.sb=sb;
}
public static void main (String args[]) {
StringBuffer sb = new StringBuffer("A");
MySyncBlockTest t1 = new MySyncBlockTest(sb);
MySyncBlockTest t2 = new MySyncBlockTest(sb);
MySyncBlockTest t3 = new MySyncBlockTest(sb);
t1.start();
t2.start();
t3.start();
}
public void run() {
synchronized(this) {
for (int i=0; i<10; i++) {
System.out.print(sb);
}
System.out.println("");
if (sb.charAt(0)=='A')
sb.setCharAt(0, 'B');
else
sb.setCharAt(0, 'C');
}
}
}
我希望输出如下(10A、10B和10C),但没有得到。
AAAAAAAAAA
BBBBBBBBBB
CCCCCCCCCC
相反,当三个线程有机会在另一个线程完成之前进入循环时,我得到了如下不同的输出。
AAAAAAAAAAAAAAAAAA
ABB
ACCCCCCCC
我的问题是为什么run方法中的synchronized块不起作用?
我也很困惑。Brian提供的答案是正确的
synchronized (this){
用于获取实例的锁。当一个类只有一个实例,并且有多个线程访问它时,这将非常有用。
我编写了以下程序来演示这一点:
package com.threads.chapter9;
public class TestSunchronizedBlocksUsingRunnable implements Runnable {
StringBuffer s;
@Override
public void run() {
synchronized (this) {
for (int i = 1; i <= 100; i++) {
System.out.println(i);
}
char c = s.charAt(0);
c++;
s.setCharAt(0, c);
}
}
TestSunchronizedBlocksUsingRunnable(StringBuffer s) {
this.s = s;
}
public static void main(String[] args) {
StringBuffer s = new StringBuffer("A");
TestSunchronizedBlocksUsingRunnable instance1 = new TestSunchronizedBlocksUsingRunnable(s);
Thread thread1 = new Thread(instance1);
Thread thread2 = new Thread(instance1);
Thread thread3 = new Thread(instance1);
thread1.start();
thread2.start();
thread3.start();
}
}
上面的代码将显示相同的输出,但是场景完全不同。所以在synchronized块中使用什么是非常重要的。
您应该锁定字符串缓冲区对象
synchronized(sb) {
for (int i=0; i<10; i++) {
System.out.print(sb);
}
4.同步的代码块将从步骤3获得StringBuffer对象上的锁。
好吧,你没有这样做,对吧?
synchronized(this) {
您正在获取调用run()
方法的MySyncBlockTest
实例的锁。那……什么也做不了。没有对该资源的争夺;每个线程都有自己的
MySyncBlockTest
实例。
问题内容: 该练习直接由Kathy Seirra和Bert Bates撰写的SCJP 同步代码块 在本练习中,我们将尝试同步代码块。在该代码块中,我们将获得对对象的锁定,以便在代码块执行时其他线程无法修改它。我们将创建三个线程,它们都将尝试操纵同一对象。每个线程将输出一个字母100次,然后将该字母加1。我们将使用的对象是StringBuffer。 我们可以在String对象上进行同步,但是一旦创建
请参阅代码。 > 当我调用方法@Async loadMarkUpPCT()时,数据没有提交到表中。它表现得好像是非牵引的。 当我从loadMarkUpPCT(类1)中删除@Async(即非异步)时,数据被提交并按预期正常:事务性) 我希望@Async和@Transactional的结果是一样的,但事实并非如此。请解释一下,我做错了什么? 编辑:我刚编辑过代码日志 流程方面:AppDataLoade
问题内容: 我正在查看包含同步方法的第三方库中的一些代码,在此方法中,有一个锁定在实例变量上的同步块。与此类似: 这有意义吗?如果是这样,在同步方法中使用同步语句有什么好处? 鉴于同步方法锁定了整个对象,对我来说似乎是多余的。在使用非私有的实例变量时,这种方法是否有意义? 问题答案: 在您的示例中,该方法 同时 锁定了和的实例。其他方法可能仅锁定对象的实例 或 对象。 因此,是的,这完全取决于他们
我试图使用RequestFuture向服务器发出同步请求,但它不起作用。使用异步完成相同的请求时效果良好。 这是我的代码: 我得到一个nullpointerexception: Java语言lang.NullPointerException:尝试调用虚拟方法的java。lang.String组织。json。J主题。com上的null对象引用上的toString()。数学应用程序。所有模块。在com
Java中的Synchronized blocks在多线程中工作时是一个很好的特性,这是非常常见的。我知道它们是如何工作的,但希望更确定它们在与等待和通知(所有)结合时是如何工作的。 通常,当一个线程进入同步块时,在第一个线程离开之前,其他线程不能进入该块。但是,当调用synchronized对象的wait时,情况就不是这样了。如果这样做了,另一个线程将无法调用notify(All),这需要在调用
我试图理解java中同步块的概念。根据我读过的文档,我明白如果我们获取一个锁(使用实例变量的同步块),那么我们就不能在该类中的同一对象上获取同步锁。但是当我尝试实际使用以下片段时,我发现我的理解出了问题。 即我能够同时以两种不同的方法获取锁(同一实例变量上的同步块)。当线程启动时,它将转到run方法并无限期地等待,并且不会从同步块中出来。同时,如果我使用相同的线程调用stop方法,它会进入同步块并