【Java基础】——之线程同步

我们先来看一段代码:

import java.util.ArrayList;

public class MyThreadTest {
	private ArrayList<String> list = new ArrayList<String>();
	private byte[] lock = new byte[0];

	private void addData() {
		list.clear();
		for (int n = 0; n < 50; n++) {
			list.add(String.valueOf(n));
		}
		System.out.println(list.size());
	}

	public static void main(String[] args) {
		final MyThreadTest mtt = new MyThreadTest();

		new Thread(new Runnable() {
			@Override
			public void run() {
				mtt.addData();
			}
		}).start();

		new Thread(new Runnable() {
			@Override
			public void run() {
				mtt.addData();
			}
		}).start();
	}
}
输出结果:50、50

在看一段代码:

import java.util.ArrayList;

public class MyThreadTest {
	private ArrayList<String> list = new ArrayList<String>();
	private byte[] lock = new byte[0];

	private void addData() {
		list.clear();
		for (int n = 0; n < 5000; n++) {
			list.add(String.valueOf(n));
		}
		System.out.println(list.size());
	}

	public static void main(String[] args) {
		final MyThreadTest mtt = new MyThreadTest();

		new Thread(new Runnable() {
			@Override
			public void run() {
				mtt.addData();
			}
		}).start();

		new Thread(new Runnable() {
			@Override
			public void run() {
				mtt.addData();
			}
		}).start();
	}
}
输出结果:8828、8971(随机的)

两份代码有什么区别?只不过是把方法中的循环次数改大了而已,但是显然第二次运行结果就不对了,为什么?

这样就引入了线程同步的概念,第一份代码自身不正确,但是运行结果为什么是正确的呢?因为循环次数过少,线程很快就执行完,所以看上去结果是“正确的”。

当我们把这样的程序引入到银行系统中我们猜猜会发生什么?O(∩_∩)O~

在进一步阐述之前,我们需要明确几点:
  A.无论synchronized关键字加在方法上还是对象上,它取得的锁都是对象,而不是把一段代码或函数当作锁――而且同步方法很可能还会被其他线程的对象访问。
  B.每个对象只有一个锁(lock)与之相关联。
  C.实现同步是要很大的系统开销作为代价的,甚至可能造成死锁,所以尽量避免无谓的同步控制。

我们看看改如何修改这个程序:

import java.util.ArrayList;

public class MyThreadTest {
	private ArrayList<String> list = new ArrayList<String>();
	private byte[] lock = new byte[0];

	synchronized private void addData() {
		list.clear();
		for (int n = 0; n < 5000; n++) {
			list.add(String.valueOf(n));
		}
		System.out.println(list.size());
	}

	public static void main(String[] args) {
		final MyThreadTest mtt = new MyThreadTest();

		new Thread(new Runnable() {
			@Override
			public void run() {
				mtt.addData();
			}
		}).start();

		new Thread(new Runnable() {
			@Override
			public void run() {
				mtt.addData();
			}
		}).start();
	}
}
当我们让addData()方法加上同步锁了之后,一次只能有一个线程访问addData()对象,其余线程出于等待状态,输出结果为:5000、5000



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值