`
CSU-NingMan
  • 浏览: 24039 次
  • 性别: Icon_minigender_2
社区版块
存档分类
最新评论

线程同步

阅读更多

 

窗外狂风大作,实在不想在睡觉时刻本着不完成誓不罢休不睡觉的精神在这邹文章。

的确,哪怕再小的知识点要吃透,不花点功夫可是没可能的。所以就线程机制给我个把星期估计也讲不明白,到头来只是重复老师的话或者网上技术牛人的博客。此刻呢,也只能绕过代码层面,说说理解和

体会吧。

首先,我习惯把知识整理成小体系,逻辑清晰,而每一块的具体当然有大把时间上网搜,进而学习。

不闲扯~

    

  •  概念,与进程联系与区别。
  • 用方法。Thread和Runnable
  • 线程游戏,熟悉线程方法使用,出错。
  • 进一步了解线程原理,工作机制,提出同步,异步概念。

接下来就同步详细介绍。异步相关概念将在后续学习中逐步介绍。

 首先,线程同步到底是什么概念?

 同步是表示线程之间存在的一种状态,还是存在的一种问题,还是解决线程共享资源被争夺的一种解决方法?

 因为“同步”二字本身容易混淆,“同”非共同,一起,而是“协作”,“配合”的意思,即“排队”,一个一个对共享资源进行操作。有这么一句话:线程同步就是线程排队,同步就是避免线程“同步“执行。

 

 综述,线程同步首先是一种解决问题的方法,即线程同步机制(动作)。也是问题被解决之后的一种状态描述,即线程之间同步了(状态)。当然,把它理解成问题的思路肯定是把“同“ 想成  ”共同“的意思。

 

  这样,理解线程同步相关概念,例如,同步锁(synchronized关键字),wait()与notify()方法,以及生产消费者模型,双缓冲,线程池等之间的联系。

 

  其次,何时需要线程同步以及为什么需要?

   A.对共享资源的使用,引起争夺与混乱。

   B.共享资源是变量,即任何线程可以改其属性

 

   举个简单的例子,线程A和线程B分别对变量x(=0)进行加1和减1的操作。而线程的执行顺序是未知的,且该操作不是原子性的,即在计算机底层连简单的+1操作也是分为3个步骤的(从内存取出,+1,放回内存),操作系统本着充分利用资源和时间响应的精神,自然会在各种调度程序的控制下,在A线程未完成加1操作之前,B线程进行减1的操作。而最终x的值无法预知。

 

 我们当然不能让这种事情让程序出错啊~那就让线程同步吧~即让线程协同配合着使用共享资源。

 

  有这么几种方法:      1.同步锁            2.等待/通知模式

 

             1.同步锁的基本思路是指:

                   对共享资源加锁,且只有一把钥匙。同一时刻只存在一个持有钥匙的线程在使用它。

                (情景:给银行账户存取款。银行初始有100元,现在启动6个线程,随即进行存取操作,显而易见,必须要线程同步.)

               A.synchronized关键字——给方法或者代码段加锁

                               a)锁定方法

 

Bank  bank=new Bank();

myThread thread1=new myThread(bank,20);

myThread thread2=new myThread(bank,-120);
myThread thread3=new myThread(bank,50);
myThread thread4=new myThread(bank,90);

myThread thread5=new myThread(bank,-40);
myThread thread6=new myThread(bank,200);
thread1.start();
.......
 

 

public class myThread extends Thread {

	
        private int money;
 	private Bank bank;


 	myThread(Bank bank, int money) {
 		this.bank = bank;
 		this.money = money;

 	}
	public void run() {

		bank.process(money);
	}

	
}
 

 

public class Bank {
	private int total = 0;

	public Bank(int total) {
		this.total = total;
	}
	public void process(int money) {
		try {
			Thread.sleep(100);
			this.total += money;

			System.out.println("对银行已操作:" + 

money + "银行现存:" + this.total);
			Thread.sleep(100);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}


}

    运行上述代码,可发现完全是混乱的,而在process()方法前加synchronized关键字即可锁定该方法,即每次只让一个线程改变账户存款。

 

            b)锁定方法块,即不是对整个方法进行锁定,只对那些操作共享资源的关键代码段进行加锁。

 

synchronized (this){

 

                this.total+=money;

System.out.println("对银行已操作:"+money+"银行

 

现存:"+bank.getTotal());

 

 

}

 

                  注意:synchronized ()括号里需要一个对象,此例中,可以直接填this,或者new一个Object对象或者一个大小为0的数组,即:

                               Object obj=new Object();

                                synchronized (obj){};

 

               B.  用Lock加锁。    

                  首先实例化一个Lock对象,在process()方法中传进去,或者利用单例模式保证每个线程拥

有的是同一把锁即可。如:

void process(int money,Lock lock) {
		try {
			lock.lock();
			Thread.sleep(100);

			this.total += money;
			System.out.println("对银行已操作:" + 

money + "银行现存:" + this.total);
			Thread.sleep(100);
			lock.unlock();
				

		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
 

 

2.等待/通知机制——wait()/notify()方法

               关于wait/notify,还有生产消费者模型与线程同步的关系,区别与应用将在后续继续呈上自己的心得哦~~

 

 

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics