【4】多线程的同步的两种方法
- 线程同步:程序中不能有多个线程同时在一段代码之间执行。
- 多线程的同步的两种方法:同步代码块、同步函数。
【4-1】同步代码块
- 为解决【3-1】中的问题,一种方法是保证以下代码的原子性。
if (Numbe > 0)
{
System.out.println(Thread.currentThread().getName() +" is saling ticket "+ Numbe--);
}
- 什么是原子性呢?可参考:
- http://blog.csdn.net/fan2012huan/article/details/51713508
http://www.parallellabs.com/2010/04/15/atomic-operation-in-multithreaded-application/
同步代码块: 就是将需要具有原子性的代码放入一个synchronized语句内,这就构成了同步代码块。例如,
synchronized(str)
{
if (Numbe > 0)
{ System.out.println(Thread.currentThread().getName() +" is saling ticket "+ Numbe--);
}
}
synchronized语句的格式为:
synchronized(object){代码段}
object可以是任意的对象,例如,
String str = new String("");
至于为什么可以是任意对象,可查阅:http://www.cnblogs.com/ygj0930/p/6561667.html 。此网址的内容描述如下:
修改代码3,得到代码4:
/*代码4*/
class TestThread implements Runnable
{
private int Numbe = 10;
String str = new String("");
public void run()
{
while(true)
{
synchronized(str)
{
if (Numbe > 0)
{
try
{
Thread.sleep(10);
}
catch (Exception e)
{
System.out.println(e.getMessage());
}
System.out.println(Thread.currentThread().getName() +" is saling ticket "+ Numbe--);
}
}
}
}
}
- 编译、运行:问题已被解决。
【4-2】同步函数
- 同步函数实现线程间的同步是,只要在需要同步的函数定义钱加上synchronized关键字即可。
/*代码5*/
class TestThread implements Runnable
{
private int Numbe = 10;
public void run()
{
while(true)
{
sale();
}
}
public synchronized void sale()
{
if (Numbe > 0)
{
try
{
Thread.sleep(10);
}
catch (Exception e)
{
System.out.println(e.getMessage());
}
System.out.println(Thread.currentThread().getName() +" is saling ticket "+ Numbe--);
}
}
}
- 编译、运行
【4-3】代码块与函数间的同步
- 要实现代码块与函数间的同步,就必须要让代码块与函数使用同一个监视器对象。
- 在同步代码块中,synchronized的监视器对象可以是任意的。
- 然而,同步代码块要与函数间同步,synchronized的监视器对象就不能是任意的,同步函数所用的监视器对象只能是this【类中的非静态方法始终能访问到的一个对象就是这个对象本身,即this】。因此,要实现代码块与函数间的同步,同步代码块中的synchronized的监视器对象只能是this。
- 以《JAVA就业培训教程》中p196-197的代码为例:
package mydemo;
class TestThread implements Runnable
{
private int Numbe = 10;
String str = new String("");
public void run()
{
if (str.equals("method"))
{
while(true)
{
sale();
}
}
else
{
synchronized(this)
{
if (Numbe > 0)
{
try
{
Thread.sleep(10);
}
catch (Exception e)
{
System.out.println(e.getMessage());
}
System.out.println( "同步代码块"+" is saling ticket "+ Numbe--);
}
}
}
}
public synchronized void sale()
{
if (Numbe > 0)
{
try
{
Thread.sleep(10);
}
catch (Exception e)
{
System.out.println(e.getMessage());
}
System.out.println("同步函数"+" is saling ticket "+ Numbe--);
}
}
}
public class ThreadDemo
{
public static void main(String[] args)
{
TestThread tDemo = new TestThread();
new Thread(tDemo).start();
try{Thread.sleep(1);}catch (Exception e){}
tDemo.str = new String("method");
new Thread(tDemo).start();
}
}
- 编译、运行: