传智博客---Java的线程同步

package com.zhou.SynchronizationOfThread;
/**
  * 线程的同步:
  *    问题:通过多线程解决小朋友分苹果的问题,一共有5个苹果,2个小朋友同时拿苹果,每次拿一个,拿完为止;
  *         --小明小朋友拿走了一个苹果,还剩4个苹果;
  *         --小强小朋友拿走了一个苹果,还剩3个苹果;
  *         --小明小朋友拿走了一个苹果,还剩2个苹果;
  *         --小强小朋友拿走了一个苹果,还剩1个苹果;
  *         --小明小朋友拿走了一个苹果,还剩0个苹果;
  *         小强的线程进入死亡状态;
  *         小明的线程进入死亡状态;
  *        
  * 线程安全:
  *   1.理解并编写出线程不安全的实例代码;
  *      多线程应用程序同时访问共享对象时,由于线程间相互抢占Cpu的控制权,造成一
  *      个线程夹在另一个线程的执行过程中运行,所以可能导致错误的执行结果;  
  *   2.使用synchronized (锁住共享的资源){}代码块来解决线程安全的问题;  
  *        ---注意:需要在synchronized代码块中参照共同的一个对象,
  *              也就是锁的就是共享资源,因为是多个线程在访问共享资源时
  *              出现线程安全的问题;    
  *       synchronized关键字:
  *            为了防止共享资源在并发访问时出现错误,Java中提供了”synchronized“关键字;
  *            synchronized关键字确保共享对象在同一时刻只只能被一个线程访问,这种处理机制称作为”线程同步“或”线程互斥“;
  *            Java中的”线程同步“基于”对象锁“的概念;        
  *        使用synchronized关键字:
  *            1.修饰方法:被”synchronized“关键字修饰的方法称为”同步方法“;
  *                //定义同步方法;
  *                public synchronized void methodName(){方法实体}
  *            2.当一个线程访问对象的同步方法时,被访问对象就处于”锁定状态“,访问该方法的其他线程只能等待,
  *              对象中的其他同步方法也不能访问,但非同步方法则可以访问;
  *            3.可以使用synchronized关键字修饰部分代码,如果只希望同步部分代码行,可以使用”同步块“;
  *                  // 同步块;
  *                  synchronized(obj){//被同步的代码块}
  *              同步块的作用与同步方法一样,只是控制范围有所区别;
  *              
  *              
  *              
  *    
  * 如何解决线程安全的问题?
  *    加锁,多个线程用一把锁;
  *
  * @author Administrator
  *
  */
public class ShareApple implements Runnable{ //这个时候两个线程用一个资源,所以使用Runnable接口;
//一共有5个苹果;
private int appleCount = 5;
  //两个小朋友来拿苹果,写一个方法;
boolean getApple(){
//怎样来给线程加锁呢,前提条件是有一个共享的对象,这里的这个ShareApple就是一个共享的对象;
synchronized (this) { //锁住这个共享的资源,如果ShareApple这个共享的资源被抢去了,我就拿这个共享资源来作为参照;
//来写如何取苹果;
if(appleCount > 0){ //只要有,我就拿;
//拿走了一个之后,总的苹果数少一个;
appleCount --;
//现在我人工的让它出现线程安全的问题;
try {
Thread.sleep(1000); //我让它停1秒钟;
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//拿了苹果之后,我还要显示下还剩多少个苹果;
System.out.println(Thread.currentThread().getName() + "拿走了一个苹果。" + "还剩" + appleCount + "个苹果。");
//总的苹果数还大于0,也就是还有苹果没被拿完,就返回的是true;
return true;
}
return false;
}
}
//线程体;
@Override
public void run() {
 //写个那苹果的标志;
boolean flag = getApple(); //首先取一下,看有没有苹果;
while(flag){ //只要有苹果的话我就取;
flag = getApple();
}
//要是没有苹果的话,就提示苹果被拿完了;
System.out.println("苹果被拿完了!"+Thread.currentThread().getName()+"-线程结束");
}
//测试的main方法;
public static void main(String[] args) {
// 创建以后实现了Runnable接口的实现类的对象;
ShareApple shareApple = new ShareApple();
//创建并启动两个线程;
Thread thread1 = new Thread(shareApple);
Thread thread2 = new Thread(shareApple);
//给线程起名字;
thread1.setName("小明");
thread2.setName("小强");
//启动线程;
thread1.start();
thread2.start();
}
}


package com.zhou.SynchronizationOfThread;
public class PrintLetters implements Runnable{
//写一个共用的char;
private char c = 'a';
//然后写一个打印;
public synchronized boolean print(){ //只要小于z的话就可以打印;
//synchronized (this) {
if(c <= 'z'){
System.out.println(Thread.currentThread().getName() + ":" + c);
 //这个中间我可以加一个锁;
//现在我要模拟出线程安全的问题,在这里让线程睡眠1秒再打印;
try {
Thread.currentThread().sleep(1000); //睡眠1秒再打印;
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//打印完之后我应该是向前走一个;
c++;
return true; //可以打印
}
return false; //否则不可以打印;
//}
}
@Override
public void run() {
//执行
             boolean flag = print();
             while(flag){ //只要flag为true的话
     flag = print(); //我就接着打印;
            }
}
//测试的main方法;
public static void main(String[] args) {
//我要两线程一千打印;
 //创建一个实现了Runnable接口的实现类对象;
PrintLetters printLetters = new PrintLetters();
//创建两个线程;
Thread thread1 = new Thread(printLetters);
Thread thread2 = new Thread(printLetters);
 //给线程起名字;
thread1.setName("线程-1");
thread2.setName("线程-2");
 //启动线程;
thread1.start();
thread2.start();
}
}


本文出自 “IT技术JAVA” 博客,转载请与作者联系!

你可能感兴趣的:(Java的线程同步)