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

来源:互联网 发布:校园网络拓扑结构设计 编辑:程序博客网 时间:2024/06/06 02:12

我们先来看一段代码:

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



原创粉丝点击