线程同步(以下介绍三种方)

线程同步(以下介绍三种方)

线程的职责就是执行一些操作,而多数操作都涉及到处理数据。这里有一个程序处理实例变量a:

     a+=i;
     a-=i;
     System.out.println(a);

线程同步的特征:

  1. 如果一个同步代码块和非同步代码块同时操纵共享资源,仍然会造成对共享资源的竞争。因为当一个线程执行一个对象的同步代码块时,其他线程仍然可以执行对象的非同步代码块。
  2. 每个对象都有唯一的同步锁。
  3. 在静态方法前面也可以使用synchronized修饰符。此时该同步锁的对象为类对象(类的Class对象)。

    1. 当一个线程开始执行同步代码块时,并不意味着必须以不中断的方式运行。进入同步代码块的线程也可以执行Thread.sleep()或者执行Thread.yield()方法,此时它并没有释放锁,只是把运行机会(即CPU)让给了其他的线程。
    2. synchnozied声明不会被继承。

    同步是解决共享资源竞争的有效手段。当一个线程已经在操纵共享资源时,其他共享线程只能等待。为了提升并发性能,应该使同步代码块中包含尽可能少的操作,使得一个线程能尽快释放锁,减少其他线程等待锁的时间。

      多个线程在操纵共享资源——实例变量时,有可能引起共享资源的况争。为了保证每个线程能正常执行操作,保证共享资源能正常访问和修改。Java引入了同步进制,具体做法是在有可能引起共享资源竞争的代码前加上synchronized标记。这样的代码被称为同步代码块。

      每个Java对象 。当一个线程试图执行带有synchronized标记的代码块时,该线程必须首先获得this关键字引用的对象的锁。

. 如果这个锁已经被其他线程占用,Java虚拟机就会把这个线程放到this指定对象的锁池中,线程进入阻塞状态。在对象的锁池中可能会有许多等待锁的线程。等到其他线程释放了锁,Java虚拟机会从锁池中随机取出一个线程,使这个线
程拥有锁,并且转到就绪状态。

. 假如这个锁没有被其他线程占用,线程就会获得这把锁,开始执行同步代码块。在一般情况下,线程只有执行完同步代码块,才会释放锁,使得其他线程能够获得锁。

如果一个方法中的所有代码都属于同步代码,则可以直接在方法前用synchronized修饰。

public synchronized String pop(){...}
      等价于
            public String pop(){
                   synchronized(this){...}
            }

1、同步”代码块“(就是将一整块代码同步)

public class AppleDemo2 {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Apple a =new Apple();

        Thread thread1 = new Thread(a,"A");
        Thread thread2 = new Thread(a,"B");
        Thread thread3 = new Thread(a,"C");

        thread1.start();
        thread2.start();
        thread3.start();



    }

}

class Apple implements Runnable{

    private int appleCount = 50;

    public void run(){


    for(int i=0;i<50;i++){
        //同步代码块锁要是唯一的,这里的this在整个代码里都是唯一的。
        //这里this等于上面的a,也就是一般将共享的线程设为锁对象
        synchronized(this){


        if(appleCount>0){

        System.out.println(Thread.currentThread().getName()+"吃苹果    "+appleCount--); 

        }
        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        }
    }

    }

}

2、同步“方法”

public class AppleDemo1 {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Apple a =new Apple();

        Thread thread1 = new Thread(a,"A");
        Thread thread2 = new Thread(a,"B");
        Thread thread3 = new Thread(a,"C");

        thread1.start();
        thread2.start();
        thread3.start();

    }

}

class Apple implements Runnable{

    private int appleCount = 50;

    public void run(){
        fangfa();

    }
    //就是把本来写在run()中的执行代码,抽象成synchronized修饰方法,然后在run()中调用即可
    //同步“方法”,用synchronizedz修饰,也可以这样写synchronized public void fangfa()
    //不过习惯于public synchronized void fangfa()写
    //这里sunchronized依然有锁,默认对应类的字节码对象
    public synchronized void fangfa(){
        for(int i=0;i<50;i++){

            if(appleCount>0){

            System.out.println(Thread.currentThread().getName()+"吃苹果    "+appleCount--); 

            }
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            }
        }
}

3、锁机制

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class LockDemo{

    public static void main(String[] args) {

        Banana a =new Banana();

        Thread thread1 = new Thread(a,"A");
        Thread thread2 = new Thread(a,"B");
        Thread thread3 = new Thread(a,"C");

        thread1.start();
        thread2.start();
        thread3.start();



    }

}

class Banana implements Runnable{

    private int bananaCount = 50;

    //这里定义一个lock类的对象,不能new本身lock只能new他的实现类
    public Lock lock = new ReentrantLock();


    public void run(){

    for(int i=0;i<50;i++){

            lock.lock();//上锁操作

        if(bananaCount>0){

        System.out.println(Thread.currentThread().getName()+"吃香蕉    "+bananaCount--); 

        }
        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally{
            lock.unlock();//开锁操作
        }
        }
    }



}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值