java中的线程同步

在java中,每一个线程都是由Thread类对象创建和控制的。通常我们有两种方式来创建一个线程,一种是继承java.lang.Thread 类,第二种是创建类的时候实现Runnable接口。下面分别介绍两种方式。

1,继承Thread类
首先创建Thread子类的一个实例,然后重写run方法,然后子类的实例必须调用start()方法之后run方法才被执行. 代码如下:

public class MultiThread extends Thread {
public void run() {
System.out.println(getName()+"线程开始运行");
for(int i = 0; i< 10; i++) {
System.out.println(i +" "+getName());
try{
sleep((int) Math.random()*10);
}catch(InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(getName() + "线程结束");
}
public static void main(String[] args) {
System.out.println(Thread.currentThread().getName()+"线程开始运行");
new MultiThread().start();
System.out.println(Thread.currentThread().getName()+"线程结束");
}
}


2,实现Runnable接口
首先我们创建一个实现Runnable接口的类ThreadRunnable,为了让线程可以执行接口中的run()方法,我们要在Thread类的构造函数中传入ThreadRunnable的一个实例,这样线程就可以执行run方法。代码如下:

public class ThreadRunnable implements Runnable {
public int count = 0;
public void run() {
System.out.println("线程开始运行");
try {
while(count <3){
Thread.sleep(300);
count++;
}
}catch (InterruptedException e) {
System.out.println("线程终止");
}
System.out.println("线程结束");
}

public static void main(String[] args) {
ThreadRunnable instance = new ThreadRunnable();
Thread thread = new Thread(instance);
thread.start();
}
}


当我们创建线程的时候,我们一般倾向于实现一个Runnable接口。因为java中不支持多重继承,如果我们继承了Thread类,那这个类就不能继承其他的类了,而如果我们实现了Runnable接口我们还可以继承其它的类。有些时候我们可能仅仅需要让线程运行就可以,当我们继承了Thread类,我们却继承了Thread类所有的方法,过于浪费。

上面简单介绍了java中如何创建线程,下面讨论一下多线程的问题。
在同一程序中运行多个线程本身不会导致问题,但如果多个线程同时访问并修改了相同的资源,就会导致问题。值得我们注意的是,这些问题只有在多个线程向这些资源做了写操作时才有可能发生,多个线程读取相同的资源就是安全的。
下面我们举个例子:

public class ThreadAdd {
public static void main(String[] args) {
MyThread instence = new MyThread();
Thread thread0 = new Thread(instence);
Thread thread1 = new Thread(instence);
thread0.start();
thread1.start();
}
}
class MyThread implements Runnable {
private int sum = 0;
public void run() {
{
if(Thread.currentThread().getName().equals("Thread-0")){
sum += 2;
}else if(Thread.currentThread().getName().equals("Thread-1"))
sum += 3;
System.out.println(sum);
}
}
}

上面的代码中thread0 和thread1执行同一个MyThread对象的方法,我们期望sum最后的结果为5,但事实上sum可能为 2,3,5。导致这个结果的原因时线程在程序中是交错执行的。当两个线程竞争同一个资源时,如果对资源的访问顺序敏感,就出现了这种情况,我们称它为竞态条件,导致竞态条件的方法称为临界区,为了避免这种情况,我们往往在临界区中使用相应的同步机制。常用的有Synchronized,Mutex, Lock和Semaphore。

对于上面的例子我们可以任意选择一种同步机制,例如使用synchronized:

public void run() {
synchronized(this){
if(Thread.currentThread().getName().equals("Thread-0")){
sum += 2;
}else if(Thread.currentThread().getName().equals("Thread-1"))
sum += 3;
System.out.println(sum);
}
}

这样就可以保证sum的最终结果为5。
对于同步锁还有信号量的问题在其他文章里详细介绍。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值