- 在多线程程序中,会出现多个线程抢占一个资源的情况,这时间有可能会造成冲突,也就是一个线程可能还没来得及将更改的 资源保存,另一个线程的更改就开始了。可能造成数据不一致。因此引入多线程同步,也就是说多个线程只能一个对共享的资源进行更改,其他线程不能对数据进行修改。
- 1.如下一个两个线程对一个银行账户进行存钱的小实例,其中使用synchornized修饰方法实现线程的同步
- 代码如下:
class bank{
private int count=100;
public synchronized void dispit() {
count+=10;
}
public int getcount() {
return count;
}
}
class ThreadCount extends Thread{
private bank count;
private JTextArea textarea = new JTextArea();
public ThreadCount(bank count,JTextArea textarea) {
= count;
= textarea;
}
public void run() {
for(int i=0; i<10; i++) {
();
("账户余额为:"+()+"\n");
}
}
}
2.同步是一种高开销的操作,因此应该尽量减少同步内容,因此也可以使用修饰代码块来代替修饰整个方法。
class bank{
private int count=100;
public void dispit() {
synchronized(this) {
count+=10;
}
}
public int getcount() {
return count;
}
}
class ThreadCount extends Thread{
private bank count;
private JTextArea textarea = new JTextArea();
public ThreadCount(bank count,JTextArea textarea) {
= count;
= textarea;
}
public void run() {
for(int i=0; i<10; i++) {
();
("账户余额为:"+()+"\n");
}
}
}
3.使用volatile修饰数据,对于当下问题,只用使用volatile来修饰账户的余额变量即可。该修饰词是对域变量的访问提供了以这种防锁机制,相当于告诉虚拟机,该域的变量可能被更改。因此每次使用该域都要重新计算,而不是从寄存器中取出数据。从而实现线程的同步。该修饰词不能修改final类型变量
class bank{
private volatile int count=100;
public void dispit() {
count+=10;
}
public int getcount() {
return count;
}
}
class ThreadCount extends Thread{
private bank count;
private JTextArea textarea = new JTextArea();
public ThreadCount(bank count,JTextArea textarea) {
= count;
= textarea;
}
public void run() {
for(int i=0; i<10; i++) {
();
("账户余额为:"+()+"\n");
}
}
}
4.使用重入锁实现线程同步。使用类ReentrantLock类来定义锁,其中lock()方法为打开锁,unlock()方法为关闭锁
类似于synchronized修饰方法有一样功能。使用锁时间需要注意应该及时放开锁,不然会进入死锁状态。一般是在finally中释放锁
class bank{
private volatile int count=100;
private Lock lock = new ReentrantLock();
public void dispit() {
();
try {
count+=10;
}finally{
();
}
}
public int getcount() {
return count;
}
}
class ThreadCount extends Thread{
private bank count;
private JTextArea textarea = new JTextArea();
public ThreadCount(bank count,JTextArea textarea) {
= count;
= textarea;
}
public void run() {
for(int i=0; i<10; i++) {
();
("账户余额为:"+()+"\n");
}
}
}
代码的输出结果如下:
可以看到,每次增加10 的时间只有一个线程在进行,也就是线程的同步
5.使用ThreadLocal类来管理。不过该方法和同步机制不相同。该类管理的变量在每个线程中都有自己的副本,副本之间相互独立,因此获得的结果和其他不同。
class bank{
private static ThreadLocal<Integer> count = new ThreadLocal() {
protected Integer initialValue() {
return 100;
}
};
private Lock lock = new ReentrantLock();
public void dispit() {
();
try {
(()+10);
}finally{
();
}
}
public int getcount() {
return ();
}
}
class ThreadCount extends Thread{
private bank count;
private JTextArea textarea = new JTextArea();
public ThreadCount(bank count,JTextArea textarea) {
= count;
= textarea;
}
public void run() {
for(int i=0; i<10; i++) {
();
("账户余额为:"+()+"\n");
}
}
}
结果如图:
可以看到,在改程序中,好比两个账户相互独立,互不干扰一样。同样解决了相同的变量访问冲突问题。