我正在尝试了解多线程(尤其是使用synchronized关键字(是如何工作的。在这个例子中,我希望第二个线程abc1在线程abc之后开始执行。所以我在run函数中使用了synchronized关键字。但输出线上写着:
此线程的初始余额为10000
此线程的原始余额为10000
是我关心的问题-243000";如输出线所示
初始243000之后的最终余额为59049000
因为abc1线程由于synchronized关键字应该等待abc。首先,我希望线程的行为就像我写一样
abc.start
abc.join()
abc1.start()
abc1.join()
这是我的源代码:
class parallel extends Thread{
account a;
public parallel(account a) {
this.a=a;
}
public synchronized void run() {
synchronized(this) {
System.out.println("Initial balance in this thread is "+a.amount);
long duplicate=a.amount;
boolean flag=true;
//System.out.println("Transaction inititated");
for(int i=0;i<10;i++) {
if(flag==true) {
//System.out.println("Deducting "+amount+"Rs from your account");
a.amount-=a.amount*2;
}
else {
//System.out.println("Depositing "+amount+"Rs from your account");
a.amount+=a.amount*2;
}
flag=!flag;
}
System.out.println("Final balance after intial "+duplicate+" is "+a.amount);
syncro.amount=a.amount;
}
}
}
class account{
public account(long rupe) {
amount=rupe;
}
long amount;
}
public class syncro {
static long amount;
public static void main(String[] args) throws InterruptedException{
//for(int i=0;i<10;i++) {
account ramesh=new account(1000);
parallel abc=new parallel(ramesh);
parallel abc1=new parallel(ramesh);
abc.start();
//abc.join();
abc1.start();
//abc1.join();
//}
//awaitTermination();
//Thread.sleep(4000);
boolean ab=true;
long cd=1000;
for(int i=0;i<10;i++) {
if(ab==true) {
//System.out.println("Deducting "+ab+"Rs from your account");
cd-=cd*2;
}
else {
//System.out.println("Depositing "+a+"Rs from your account");
cd+=cd*2;
}
ab=!ab;
}
//System.out.println("Final amount by multithreading is "+);
System.out.println("Final amount after serial order is "+cd);
}
}
您将创建自己的线程与使用synchronized混合在一起。此外,在同步方法中使用synchronized(this(就是两次做同样的事情。
同步不是启动线程。它是关于一次只允许一个线程输入特定的代码块。
您创建的每个对象都有一个无法读取的隐藏字段,但它确实存在。它的类型为Thread,称为owner
。
synchronized
关键字与此隐藏字段交互。
synchronized (object) {
code();
}
指以下内容:
- 如果是
object.owner == Thread.currentThread()
,则继续进行并递增计数器 - 如果是
object.owner == null
,则运行object.owner = Thread.currentThread()
,将计数器设置为1,然后继续运行 - 否则(因此,object.owner是其他线程(,停止,冻结线程,等待所有者设置为null,然后我们可以转到选项#2
- 一旦我们进入,运行code((。当我们到达右大括号时,递减计数器。如果为0,则运行
object.owner = null
- 此外,以上所有操作都是原子地完成的——2个线程不可能在执行所有这些操作时进入竞争状态。例如,如果有两个线程正在等待所有者再次取消设置,那么只有一个线程会"获取它",另一个线程将继续等待。(哪一个得到了它?VM impl可以自由选择它想要的任何东西;你应该认为它是任意的,但不公平。换句话说,不要写依赖于特定选择的代码(
- 用
synchronized
编写关键字的方法只是语法糖,用于将其内部的所有代码封装在synchronized(this)
(例如方法(和synchronized(MyClass.this)
(静态方法(中
请注意,synchronized
因此仅与其他synchronized
块交互,并且仅与括号中的对象是完全相同的obj引用的块交互,否则这些都不会起任何作用。它肯定不会启动线程!所有同步的操作都可能会暂停线程。
在您的代码中,您将所有运行代码放在一个巨大的同步块中,在线程实例上同步。一般来说,当你在任何事情上同步时,它是公共的API——其他代码可以在同一件事情上同步并影响你。就像我们通常不在java中编写公共字段一样,您应该不锁定公共内容,并且this
通常是公共的(就像在中一样,您不控制的代码可以包含对您的引用(。所以,除非你愿意在你的文档中详细说明你的锁定行为是如何设置的,否则不要这样做。相反,创建一个内部私有的final字段,将其称为lock,并使用它(private final Object lock = new Object();
(。