虽然做java已经两年多了,但说真的对java中所谓的线程同步异步这类的东东还真不是非常的了解,由于最近在研究android上的游戏开发,看到一个游戏demo里到处都充斥着 synchronized这个关键字,而且由于在游戏开发中对线程的使用十分多,所以便写下了这些东东(高手直接忽略就可以了)。
若有幸被高手看到了这篇博文,如果有错误的话请指出,不胜感激。
关于synchronized关键字我自己写了个测试程序运行了一下,具体情况如下:
先把测试代码贴上来看看:
测试代码1:
class TxtThread implements Runnable { int num = 4; String str = new String(); @Override public void run() { // TODO Auto-generated method stub int i = 0; while(i < 5){ synchronized (str) { if(num > 0){ try { System.out.println(Thread.currentThread().getName() + " : " + i); Thread.sleep(500); } catch (InterruptedException e) { // TODO Auto-generated catch block e.getMessage(); } i++; } } } } }
测试代码2:
运行Sync的结果如下:
运行结果1
第一次运行B : 0 B : 1 B : 2 B : 3 C : 0 C : 1 A : 0 D : 0 A : 1 A : 2 A : 3 C : 2 C : 3 C : 4 B : 4 A : 4 D : 1 D : 2 D : 3 D : 4 ----------- 第二次运行A : 0 A : 1 D : 0 D : 1 D : 2 D : 3 D : 4 B : 0 B : 1 C : 0 C : 1 B : 2 B : 3 B : 4 A : 2 A : 3 A : 4 C : 2 C : 3 C : 4 -----------从上面的运行结果来看,线程A、B、C、D都是逐个运行的,只不过这四个线程在运行过程中出现了对系统资源的竞争(我是这么理解的),所以导致了上面的情况发生(比如线程A运行了两步然后线程D又运行了三步,我认为这种情况是线程之间对系统资源的竞争引起的),但有一个地方是可以看出来的,线程A、B、C、D并没有同时开始运行,莫非这就是所谓的互斥?
将TxtThread类的run方法中的代码去掉synchronized包裹层去掉,运行结果如下
运行结果2
第一次运行B : 0 D : 0 A : 0 C : 0 B : 1 D : 1 C : 1 A : 1 B : 2 D : 2 C : 2 A : 2 D : 3 B : 3 A : 3 C : 3 D : 4 B : 4 A : 4 C : 4 ----------- 第二次运行A : 0 C : 0 B : 0 D : 0 A : 1 C : 1 B : 1 D : 1 A : 2 B : 2 C : 2 D : 2 A : 3 C : 3 B : 3 D : 3 C : 4 B : 4 A : 4 D : 4从上面的运行结果来看,线程A、B、C、D是同时开始运行的,莫非这就是所谓的同步访问?
下面的内容引用自http://java.chinaitlab.com/base/818583.html
在java编程思想中对synchronized的一点解释: 1、synchronized关键字的作用域有二种: 1)是某个对象实例内,synchronized aMethod(){}可以防止多个线程同时访问这个对象的synchronized方法(如果一个对象有多个synchronized方法,只要一个线程访问了其中的一个synchronized方法,其它线程不能同时访问这个对象中任何一个synchronized方法)。这时,不同的对象实例的synchronized方法是不相干扰的。也就是说,其它线程照样可以同时访问相同类的另一个对象实例中的synchronized方法; 2)是某个类的范围,synchronized static aStaticMethod{}防止多个线程同时访问这个类中的synchronized static 方法。它可以对类的所有对象实例起作用。 2、除了方法前用synchronized关键字,synchronized关键字还可以用于方法中的某个区块中,表示只对这个区块的资源实行互斥访问。用法是: synchronized(this){/*区块*/},它的作用域是当前对象; 3、synchronized关键字是不能继承的,也就是说,基类的方法synchronized f(){} 在继承类中并不自动是synchronized f(){},而是变成了f(){}。继承类需要你显式的指定它的某个方法为synchronized方法;
从上面引用的内容来看,当测试程序中的TxtThread中的synchronized没有被删除的时候,相当于4个线程(A、B、C、D)同时访问了一个对象的同步方法,那么当线程A、B、C、D全部执行start方法时,它们应该是首先对系统资源进行竞争获得运行时间然后占用TxtThread的run方法中的同步语句块部分,直到某个线程运行完成之后才能允许下一个线程,这样理解的话感觉跟上面的运行结果1不结果不一样,我看了一下资料,我们在TxtThread的run方法中只是对部分关键代码进行了同步,也就是说不同的线程还是可以同时访问TxtThread方法中的run方法的,如果我们将TxtTHread的run方法中的内容写入到另外一个方法runtest()方法中,并将runtest()方法使用synchronized函数进行修饰并将其放到TxtThread的run方法中调用,那么我们就会看到下面的运行效果了,
这样就符合引用内容中的第一条所说的情况了