您当前的位置: 首页 > 学无止境 > 心得笔记 网站首页心得笔记
javase第三季学习笔记-线程同步与死锁
发布时间:2017-08-10 16:15:52编辑:雪饮阅读()
多线程共享数据
• 在多线程的操作中,多个线程有可能同时处理同一个资源,这就是多线程中的共享数据。
示例代码:当一个线程sleep的时候另外一个线程也可以执行该线程的程序
package com.vince.thread;
public class ThreadDemo {
public static void main(String[] args) {
Mythread my=new Mythread();
Thread t1=new Thread(my,"小白");
Thread t2=new Thread(my,"小黑");
t1.start();
t2.start();
}
}
class Mythread implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"开始");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"完毕");
}
}
线程同步
• 解决数据共享问题,必须使用同步,所谓同步就是指 多个线程在同一个时间段内只能有一个线程执行指定代码,其他线程要等待此线程完成之后才可以继续执行。
• 线程进行同步,有以下两种方法:
• (1)同步代码块
• synchronized(要同步的对象){
• 要同步的操作 ;
• }
• (2)同步方法
• public synchronized void method(){
• 要同步的操作 ;
• }
示例代码:同步代码块
package com.vince.thread;
public class ThreadDemo {
public static void main(String[] args) {
Mythread my=new Mythread();
Thread t1=new Thread(my,"小白");
Thread t2=new Thread(my,"小黑");
t1.start();
t2.start();
}
}
class Mythread implements Runnable{
@Override
public void run() {
//实例化一个任意对象,同步的标记对象
Object obj=new Object();
/*
同步代码块,参数可以是任意对象
如果在内存中obj状态默认值为0,状态为0代表锁被释放的状态
有如下场景:
例如t1线程执行到此处发现状态为0,则将状态加1,该线程遇到sleep时先暂停,暂停期间恰逢其它线程也进来,但其它线程发现
obj状态不为0则等待。
当本线程的sleep完毕后将整个同步块中的代码都执行完毕后则将obj减1.然后其它线程又可以进来了。
*/
synchronized (obj) {
System.out.println(Thread.currentThread().getName()+"开始");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"完毕");
}
}
}
示例代码:同步方法
package com.vince.thread;
public class ThreadDemo {
public static void main(String[] args) {
Mythread my=new Mythread();
Thread t1=new Thread(my,"小白");
Thread t2=new Thread(my,"小黑");
t1.start();
t2.start();
}
}
class Mythread implements Runnable{
@Override
public void run() {
deMethod();
}
/*
同步方法不用传递一个对象作为参数,因为同步方法以当前对象作为参数
但是有一个缺陷,如果有多个同步方法,由于使用的是同一个对象都是当前对象,则一个方法被锁上了,另外一个方法也会被锁上
*/
public synchronized void deMethod(){
System.out.println(Thread.currentThread().getName()+"开始");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"完毕");
}
}
同步准则
• 当编写 synchronized 块时,有几个简单的准则可以遵循,这些准则在避免死锁和性能危险的风险方面大有帮助:
• (1)使代码块保持简短。把不随线程变化的预处理和后处理移出synchronized 块。
• (2)不要阻塞。如InputStream.read()。
• (3)在持有锁的时候,不要对其它对象调用方法。因为这样做有可能带来死锁的问题,其它对象的某个方法有可能也是同步的,那么有可能会造成当前线程等着这个其它对象释锁,而其它对象也可能等待本对象释锁。
线程死锁
• 过多的同步有可能出现死锁,死锁的操作一般是在程序运行的时候才有可能出现。
• 多线程中要进行资源的共享,就需要同步,但同步过多,就可能造成死锁
示例代码:
package com.vince.thread;
public class ThreadDemo {
public static void main(String[] args) {
new DeadThread();
}
}
//顾客类
class Customer{
public synchronized void say(Waiter w){
System.out.println("顾客说:先做再给钱!");
w.doService();
}
public synchronized void doService(){
System.out.println("顾客同意了,先给钱,再做");
}
}
//服务生类
class Waiter{
public synchronized void say(Customer c){
System.out.println("服务生说:先给钱,再做");
c.doService();
}
public synchronized void doService(){
System.out.println("服务生同意了,先做再给钱");
}
}
//死锁线程,死锁有几率出现,调用的同步方法越多,当出现多线程时造成死锁的几率越高
class DeadThread implements Runnable{
Customer c=new Customer();
Waiter w=new Waiter();
public DeadThread(){
new Thread(this).start();
w.say(c);;
}
public void run(){
c.say(w);
}
}
关键字词:javase,线程同步与死锁
上一篇:javase第三季学习笔记-注解