五、线程的同步(加锁 )

五、线程的同步(加锁 )

1、为什么需要同步

0~10的和采用相同的线程对象启用两个线程进行计算 ( 共享一个对象启动两个线程 )

public class ThreadTest {
public static void main(String[] args) {
Runnable r1 = new Processor();
Thread t1 = new Thread(r1, "t1");
t1.start();


Thread t2 = new Thread(r1, "t2");
t2.start();
}
}


class Processor implements Runnable {


@Override
public void run() {
// TODO Auto-generated method stub
int s = 0;
for (int i = 0; i < 10; i++) {
s += i;
}
System.out.println(Thread.currentThread().getName() + ",s=" + s);
}


}

以上 t1t2并发执行, s为每个线程的局部变量,位于各自的栈帧中,因为栈帧中的数据

是不会互相干扰的,所有计算结果都为45

0~10的和采用两个线程进行计算, s改为成员变量(共享一个对象启动两个线程 )

public class ThreadTest {
public static void main(String[] args) {
Runnable r1 = new Processor();
Thread t1 = new Thread(r1, "t1");
t1.start();


Thread t2 = new Thread(r1, "t2");
t2.start();
}
}


class Processor implements Runnable {


private int s = 0;

@Override
public void run() {
// TODO Auto-generated method stub

for (int i = 0; i < 10; i++) {
s += i;
}
System.out.println(Thread.currentThread().getName() + ",s=" + s);
}


}

为什么出现以上的问题,因为共享了同一个对象的成员变量s,两个线程同时对其进行操作,
所以产生了问题,此时称为此时
Processor为线程不安全的,如果想得到正确的结果,必须

采用线程同步,加锁,该变量不能共享使用。


2、使用线程同步

线程同步,指某一个时刻,指允许一个线程来访问共享资源,线程同步其实是对对象加锁,
如果对象中的方法都是同步方法, 那么某一时刻只能执行一个方法, 采用线程同步解决以上
的问题, 我们只要保证线程一操作
s时, 线程2不允许操作即可,只有线程一使用完成 s后,

再让线程二来使用s变量

public class ThreadTest {
public static void main(String[] args) {
Runnable r = new Processor();
Thread t1 = new Thread(r, "t1");
t1.start();


Thread t2 = new Thread(r, "t2");
t2.start();
}
}




class Processor implements Runnable {


private int s = 0;

@Override
public synchronized void run() {
// TODO Auto-generated method stub

synchronized(this){
for (int i = 0; i < 10; i++) {
s += i;
}
System.out.println(Thread.currentThread().getName() + ",s=" + s);
s= 0;
}
}


}

以上示例, 如果不采用线程同步如何解决?可以让每个线程创建一个对象, 这样在堆中就不

会出现对象的状态共享了,从而可以避免线程安全问题


3、为每一个线程创建一个对象来解决线程安全问题

public class ThreadTest {
public static void main(String[] args) {
Runnable r1 = new Processor();
Thread t1 = new Thread(r1, "t1");
t1.start();


Runnable r2 = new Processor12();
Thread t2 = new Thread(r2, "t2");
t2.start();
}
}


class Processor implements Runnable {


private int s = 0;

@Override
public void run() {
// TODO Auto-generated method stub

for (int i = 0; i < 10; i++) {
s += i;
}
System.out.println(Thread.currentThread().getName() + ",s=" + s);
}


}

以上输出完全正确,每个线程操作的是自己的对象,没有操作共享的资源



猜你喜欢

转载自blog.csdn.net/sky198989/article/details/81055453