同步和锁

多线程的安全的原因
1.多个线程在操作共享的数据
2.操作共享数据的代码有多条
当一个线程再行操作共享数据的多条语句,其他线程参与了运算

问题:
在一个程序中有一个数据被多条线程所操作,导致结果出错如何避免(不同步)
示例代码:

public class Text_Thread
{
    public static void main(String[] args)
    {
    TicketOfRunnable t1 = new TicketOfRunnable();
    TicketOfRunnable t2 = new TicketOfRunnable();

    Thread a = new Thread(t1);
    Thread b = new Thread(t1); 
    Thread c = new Thread(t1);
    Thread d = new Thread(t1);
   //定义四个线程类的对象,
    a.start();

    b.start();

    c.start();

    d.start();
   //将四个线程对象开启
    }
}
class TicketOfRunnable implements Runnable
{
    private int IDnumber = 5;

    public void run() 
    {
        while(true)
        {
              if(IDnumber > 0)
              {
                 try
                 {
                    Thread.sleep(10);//让线程休眠一小会
                 }
                 catch (InterruptedException e) 
                 {}
                //让线程休眠的目的是降低不同的线程切换的速度                  System.out.println(Thread.currentThread().getName()+"...."+IDnumber--);
              }
        }
    }
}

运行结果:

Thread-0….4
Thread-1….5
Thread-3….2
Thread-2….3
Thread-1….0
Thread-2….1
Thread-3….-1
Thread-0….-2

//出现了小于等于0的结果

解决方法:
将多条共享数据的代码封装起来,当有线程在执行这些代码的时候,其他线程不能进入,执行完毕之后,其他线程才能参与运算
关键字
synchronized(obj) //这个代码块是有参数的(对象)
{ 所要封装的代码块 }
示例代码:

public class Text_Thread
{
    public static void main(String[] args)
    {
    TicketOfRunnable t1 = new TicketOfRunnable();
    TicketOfRunnable t2 = new TicketOfRunnable();

    Thread a = new Thread(t1);
    Thread b = new Thread(t1);  
    Thread c = new Thread(t1);
    Thread d = new Thread(t1);

    a.start();  
    b.start();
    c.start();
    d.start();  
    }
}

class TicketOfRunnable implements Runnable
{
    private int IDnumber = 5;

    Object obj = new Object();
    public void run() 
    {
        while(true)
        {
            synchronized(obj)
            {
              if(IDnumber > 0)
              {
                 try
                 {
                    Thread.sleep(10);//让线程休眠一小会
                 }
                  catch (InterruptedException e) 
                  {}

                 System.out.println(Thread.currentThread().getName()+"...."+IDnumber--);
              }
            }

        }
    }
}

运行结果:

运行结果:
Thread-0….5
Thread-2….4
Thread-2….3
Thread-2….2
Thread-2….1

1.如果即使使用了同步锁还是没有解决问题考虑下面的问题
同步的前提:必须有多个线程使用同一个锁
一把对象锁的实现:

class TicketOfRunnable implements Runnable
{
    private int IDnumber = 5;

    Object obj = new Object();  //只创建一次这个对象
    public void run() 
    {
        while(true)
        {
            synchronized(obj)
            {
              。。。。。。
         }
       }
    }
 //正确可以确保同步

错误的使用多把对象锁示例:

class TicketOfRunnable implements Runnable
{
    private int IDnumber = 5;

    public void run() 
    {
      Object obj = new Object();//随着线程的进入都要进行对象创建(相当于多锁)
        while(true)
        {
            synchronized(obj)
            {
              ....
         }
      }
   }

2.同步函数
关键字synthrontic直接放在函数的关键字中

public synchronized void add(int num) //同步函数

同步函数的锁
功能也是实现同步,但是同步函数的锁与同步代码块的锁不是同一个锁,同步函数的锁就是在创建线程是传入的对象(this)
示例代码:

public class SynFunctionLockDemo
{
    public static void main(String[] args)
    {
        TicketOfRunnable t1 = new TicketOfRunnable();

        Thread a1 = new Thread(t1);
        Thread a2 = new Thread(t1);

        a1.start();

        try{Thread.sleep(10);}  catch(InterruptedException e) {}  //让主线程进入睡眠
        t1.FLAG = false;
        a2.start();
    }
}

3.静态同步方法(锁)
静态函数直接就加载进方法区是字节码文件对象(getClass)
获取字节码文件对象:
Class clazz = TicketOfRunnable.class
//获取字节码文件的对象
class calzz = t1.getClass();
//创建了对象以后来获取字节码文件对象

介绍一种可以切换同步代码块与同步函数的方法
示例代码:

class TicketOfRunnable implements Runnable
{
    private int IDnumber = 5;

    Object obj = new Object();
    boolean FLAG = true;

    public void run()
    {
        if(FLAG)
        {
            while(true)
            {
                synchronized(obj)
                {
                    fun("同步代码块");
                }
            }
        }
        else
        {
            while(true)
                show();
        }
    }

    public synchronized void show()
    {
        fun("同步函数");
    }

    //将原来的代码中重复的部分进行抽取,用函数封装起来

运行结果:

Thread-0….同步代码块5
Thread-0….同步代码块4
Thread-1….同步函数4
Thread-1….同步函数3
Thread-0….同步代码块3
Thread-1….同步函数2
Thread-0….同步代码块2
Thread-1….同步函数1
Thread-0….同步代码块1

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值