例子:
public class MYThread extends Thread {
private int count = 5;
public MYThread(String name) {
super();
this.setName(name);//设置线程的名字
}
@Override
public void run() {
super.run();
while (count > 0) {
count -- ;
System.out.println("由 "+this.currentThread().getName()+" 计算,count= "+count);
}
}
}
public class TetsMYThread {
public static void main(String[] args) {
MYThread t1 = new MYThread("A");
MYThread t2 = new MYThread("B");
MYThread t3 = new MYThread("C");
t1.start();
t2.start();
t3.start();
}
}
上面创建了三个线程。 每个线程都有自己的计数变量,并减少自己变量的计数值。 在这种情况下,变量不是共享的,多个线程不会访问同一个实例变量。
改进后的代码:
public static void main(String[] args) {
MYThread t = new MYThread();
Thread t1 = new Thread(t,"A");
Thread t2 = new Thread(t,"B");
Thread t3 = new Thread(t,"C");
Thread t4 = new Thread(t,"D");
Thread t5 = new Thread(t,"E");
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
}
public class MYThread extends Thread {
private int count = 5;
@Override
public void run() {
super.run();
count--;
System.out.println("由 " + this.currentThread().getName()
+ " 计算,count= " + count);
}
}
AC 两个线程同时打印的count值为3,说明两个线程同时处理count,导致“非线程安全问题”。 我们想要打印的是结果不是重复的,而是按顺序减少的。
在一些JVM中,i--操作分为3步:
1.取出原来的i值
2. 计算i-1
3. 给i赋值
这三个步骤中,如果多个线程同时访问的话,肯定会出现非线程安全问题。
再次改进代码:
public class MYThread extends Thread {
private int count = 5;
@Override
synchronized public void run() {
super.run();
count--;
System.out.println("由 " + this.currentThread().getName()
+ " 计算,count= " + count);
}
}
在run方法中添加关键字,这样当多个线程执行run方法时,就会在队列中进行处理。 线程在调用run方法之前,首先判断run方法是否被锁定。 如果被锁定,说明其他线程正在调用run方法,则必须等待其他线程完成对run方法的调用,然后才能执行run方法。 这样就达到了对调用进行排队的目的,同时也实现了按顺序计数- -,并且可以锁定任何对象和方法。 枷锁的代码称为“互斥区”或“临界区”。
再次了解
当一个线程想要执行同步方法中的代码时,该线程首先尝试获取锁。 如果能拿到,那么线程就可以执行里面的代码了。 如果它无法获取它,那么线程将继续尝试获取它。 拿着这把锁直到你得到它。 请注意,多个线程同时竞争此锁。 。 。