我正在尝试理解java中的synchronized块。
在C / C ++中,我们使用互斥锁来保护关键部分。所以,如果一个对象有两个资源,比如i和j,并且如果有两个接口SetI和SetJ分别修改i和j,我会声明两个互斥锁,每个互斥锁保护i和j,简单!
现在我试图在java中模拟相同的东西。
考虑进入synchronized(obj)并想要修改其成员i的线程。
然后,我可以没有另一个线程进入不同的同步块但是同一个对象,需要修改obj的其他成员名为j?
我附加了一个试图执行上述任务的示例代码,但只有一个线程获得了机会,另一个想要修改其他变量的线程永远不会有机会。
如果要保护的资源是对象,我将对成员本身进行同步,i和j。但由于这些是原始数据类型,我不能在synchronized中使用它们(我试过,但得到了编译错误)。所以,我被迫同步“这个”。
问题不在于为什么只有一个线程有机会执行我理解的内容。相反,我如何实现我的要求,即“修改对象的两个不同资源的两个线程不应该相互阻塞”。
class object
{
private boolean i;
private boolean j;
public void flipi(String arg)
{
synchronized(this)
{
while(true)
{
i = !i;
System.out.println("flipi "+ "thread: " + arg + " value of i: " + i);
try
{
Thread.sleep(2000);
}
catch(Exception e)
{
System.out.println(e);
}
}
}
}
public void flipj(String arg)
{
synchronized(this)
{
while(true)
{
j = !j;
System.out.println("flipj "+ "thread: " + arg + " value of j: " + j );
try
{
Thread.sleep(2000);
}
catch(Exception e)
{
System.out.println(e);
}
}
}
}
}
class test extends Thread
{
object obj;
test(object obj)
{
this.obj = obj;
}
@Override
public void run()
{
String threadname = Thread.currentThread().getName();
if(threadname.equals("test1"))
{
obj.flipi(Thread.currentThread().getName());
}
else if(threadname.equals("test2"))
{
obj.flipj(Thread.currentThread().getName());
}
}
}
public class testsynchronized
{
public static void main(String[] args)
{
object obj = new object();
test t1 = new test(obj);
test t2 = new test(obj);
t1.setName("test1");
t2.setName("test2");
t1.start();
t2.start();
}
}
输出:
$ java testsynchronized
flipj thread: test2 value of j: true
flipj thread: test2 value of j: false
flipj thread: test2 value of j: true
flipj thread: test2 value of j: false
flipj thread: test2 value of j: true
flipj thread: test2 value of j: false
flipj thread: test2 value of j: true
flipj thread: test2 value of j: false
flipj thread: test2 value of j: true
flipj thread: test2 value of j: false
flipj thread: test2 value of j: true
flipj thread: test2 value of j: false
flipj thread: test2 value of j: true
flipj thread: test2 value of j: false
flipj thread: test2 value of j: true
flipj thread: test2 value of j: false
flipj thread: test2 value of j: true
flipj thread: test2 value of j: false
flipj thread: test2 value of j: true
flipj thread: test2 value of j: false
flipj thread: test2 value of j: true
flipj thread: test2 value of j: false
flipj thread: test2 value of j: true
flipj thread: test2 value of j: false
flipj thread: test2 value of j: true
flipj thread: test2 value of j: false
flipj thread: test2 value of j: true
flipj thread: test2 value of j: false
flipj thread: test2 value of j: true
flipj thread: test2 value of j: false
flipj thread: test2 value of j: true
flipj thread: test2 value of j: false
flipj thread: test2 value of j: true
flipj thread: test2 value of j: false
flipj thread: test2 value of j: true
flipj thread: test2 value of j: false
flipj thread: test2 value of j: true
flipj thread: test2 value of j: false
flipj thread: test2 value of j: true
flipj thread: test2 value of j: false
flipj thread: test2 value of j: true
答案 0 :(得分:1)
在同步块中有一个无限循环,它们都在同一个事物上同步(this
)。一旦一个线程进入它,它就不会离开,所以没有其他线程可以进入同步块。
要允许不同的线程更新不同的变量而不会相互干扰,请在不同的事情上同步这些变量的更新:
private final Object iGuard = new Object();
private final Object jGuard = new Object();
然后:
synchronized (iGuard) { i = !i; }
和
synchronized (jGuard) { j = !j; }
顺便说一句,在线程名称上切换行为基本上不是正确的事情。只需像这样创建你的主题:
Thread t1 = new Thread(a -> a.flipi("Thread 1"));
Thread t2 = new Thread(a -> a.flipj("Thread 2"));
t1.start();
t2.start();
答案 1 :(得分:1)
而不是同步'这个'您可以创建2个不同的锁定对象并对其进行同步:
class object
{
private boolean i;
private boolean j;
Object lock1 = new Object();
Object lock2 = new Object();
public void flipi(String arg)
{
synchronized(lock1)
{
while(true)
{
i = !i;
System.out.println("flipi "+ "thread: " + arg + " value of i: " + i);
try
{
Thread.sleep(2000);
}
catch(Exception e)
{
System.out.println(e);
}
}
}
}
public void flipj(String arg)
{
synchronized(lock2)
{
while(true)
{
j = !j;
System.out.println("flipj "+ "thread: " + arg + " value of j: " + j );
try
{
Thread.sleep(2000);
}
catch(Exception e)
{
System.out.println(e);
}
}
}
}
}
class test extends Thread
{
object obj;
test(object obj)
{
this.obj = obj;
}
@Override
public void run()
{
String threadname = Thread.currentThread().getName();
if(threadname.equals("test1"))
{
obj.flipi(Thread.currentThread().getName());
}
else if(threadname.equals("test2"))
{
obj.flipj(Thread.currentThread().getName());
}
}
}
public class testsynchronized
{
public static void main(String[] args)
{
object obj = new object();
test t1 = new test(obj);
test t2 = new test(obj);
t1.setName("test1");
t2.setName("test2");
t1.start();
t2.start();
}
}
答案 2 :(得分:0)
你可以看到,
while(true)
正在运行调用flipi("threadName")
的run()方法
这意味着它从不打电话
else if(threadname.equals("test2"))
并且只有第一个flipi
方法在循环中运行
要理解相同的事情,除了进入无限循环
之外,尝试别的东西