多线程并发问题(一)

一、线程两种创建方式:

1.继承Thread类创建线程:

public class FirstThreadTest extends Thread {
    public void run(){
        System.out.println("这里是线程的执行方法");
    }

    public static void main(String[] args) {
        //获得线程
        FirstThreadTest thread = new FirstThreadTest();
        System.out.println("线程名称为:"+thread.getName());
        //启动线程
        thread.start();
        System.out.println("main方法也是一个线程:"+Thread.currentThread().getName());
    }
}

2.实现Runnable接口创建线程:

  •  (1)定义runnable接口的实现类,并重写该接口的run()方法,该run()方法的方法体同样是该线程的线程执行体;
  •  (2)创建 Runnable实现类的实例,并依此实例作为Thread的target来创建Thread对象,该Thread对象才是真正的线程对象;
  •  (3)调用线程对象的start()方法来启动该线程。
public class RunnableThreadTest implements Runnable {

    public void run() {
        System.out.println("这里是线程方法");
        System.out.println("线程名为:" + Thread.currentThread().getName());
    }

    public static void main(String[] args) {
        System.out.println("main方法线程:" + Thread.currentThread().getName());
        RunnableThreadTest rtt = new RunnableThreadTest();
        new Thread(rtt, "新线程1").start();
        new Thread(rtt, "新线程2").start();
    }

}

 

二、多线程并发的主要引发的两个问题:

    1.多线程共享数据同步问题:synchronized
              <1>多个线程共享同一个数据时,那面会出现抢占,错拿等问题。。

              <2>线程安全问题:

  •         两个同时从一个箱子里面拿苹果,两个人就是两个线程,箱子里的苹果是他们共享的数据;当两个人同时把手放到箱子里面时就会发生线程安全的问题,如:两个人拿到同一个苹果 发生互不想让的情况;
  •         比如共20个苹果,当A刚好把苹果拿到手上,总数还没有进行减一操作时,B就来了 所以它认为的苹果总数还是20 但是实际已经是19了,就会线程不安全;

               <3>线程安全解决:synchronized关键字(对象锁---尽量锁在范围小的地方,提高效率);

                   synchronized:当用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码;

               <4> 当run()方法发生异常,而且没有得到解决时,该线程会终止,但不会影响该进程中的其他线程;

2.数据因并发产生不一致问题:ThreadLocal

                ThreadLocal:为每一个线程都提供了变量的副本,使得每个线程在某一时间访问到的并不是同一个对象。

                <1>ThreadLocal 不是用来解决共享对象的多线程访问问题的,通过ThreadLocal.set()到线程自己的对象,其他线程下能不需要访问,也访问不到,各个线程反复问额对象都是不一样的,因此不用考虑共享对象的问题;

                <2>ThreadLocal使得各线程能够保持各自独立的一个对象,并不是通过ThreadLocal.set()来实现的,而是通过每个线程中的new 对象的操作来创建的对象(new 了一个新线程对象,而不是引用一个对象),每个线程创建一个,不是什么对象的拷贝或副本。

 

 ThreadLocal和Synchonized都用于解决多线程并发访问。但是ThreadLocal与synchronized有本质的区别:

  • 1、synchronized关键字主要解决多线程共享数据同步问题,ThreadLocal使用场合主要解决多线程中数据因并发产生不一致问题;
  • 2、synchronized是利用锁的机制,使变量或代码块在某一时该只能被一个线程访问。而ThreadLocal为每一个线程都提供了变量的副本,使得每个线程在某一时间访问到的并不是同一个对象,这样就隔离了多个线程对数据的数据共享。而Synchronized却正好相反,它用于在多个线程间通信时能够获得数据共享;
  • 3.Synchronized用于线程间的数据共享,而ThreadLocal则用于线程间的数据隔离;
  • 4.ThreadLocal本质上不是Thread ,而是线程局部变量(ThreadLocal)其实的功用非常简单,就是为每一个使用该变量的线程都提供一个变量值的副本,是Java中一种较为特殊的线程绑定机制,是每一个线程都可以独立地改变自己的副本,而不会和其它线程的副本冲突。 
  • 5.ThreadLocal维护变量副本:在ThreadLocal类中有一个Map,用于存储每一个线程的变量的副本。 
  • 6.概括起来说,对于多线程资源共享的问题,同步机制采用了“以时间换空间”的方式,而ThreadLocal采用了“以空间换时间”的方式。前者仅提供一份变量,让不同的线程排队访问,而后者为每一个线程都提供了一份变量,因此可以同时访问而互不影响。
  • 7.按照传统经验,如果某个对象是非线程安全的,在多线程环境下,对对象的访问必须采用synchronized进行线程同步。但Spring的DAO模板类并未采用线程同步机制,因为线程同步限制了并发访问,会带来很大的性能损失。
  • 8.在无需同步的情况下就化解线程安全的难题---ThreadLocal在Spring中发挥着重要的作用,在管理request作用域的Bean、事务管理、任务调度、AOP等模块都出现了它们的身影,起着举足轻重的作用。

 

参考:https://blog.csdn.net/u012385190/article/details/53302239

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值