多线程基础

一、进程和线程的关系
CPU轮流给每个进程及线程分配时间。总结一下二者关系:
a>.一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程。线程是操作系统可识别的最小执行和调度单位。
b>.资源分配给进程,同一进程的所有线程共享该进程的所有资源。 同一进程中的多个线程共享代码段(代码和常量),数据段(全局变量和静态变量),扩展段(堆存储)。但是每个线程拥有自己的栈段,栈段又叫运行时段,用来存放所有局部变量和临时变量。
c>.处理机分给线程,即真正在处理机上运行的是线程。
d>.线程在执行过程中,需要协作同步。不同进程的线程间要利用消息通信的办法实现同步。
二、Java实现多线程的基本方式
1、实现Runnable接口
2、继承Thread类
三、ReentrantLock 类
Lock lock = new ReentrantLock();
lock.lock();
try {
// update object state
}
finally {
lock.unlock();
}
确实需要一些 synchronized 所没有的特性的时候,比如时间锁等候、可中断锁等候、无块结构锁、多个条件变量或者轮询锁。
它与synchronized的区别:
1、等待可中断:可以设置中断过期时间获取方式为 在声明的时候调用lockinterruptibly()方法,当需要中断时调用interrupt()方法
2、公平锁:公平锁是指当线程阻塞时线程的执行顺序是按照加入的时间执行的。synchronized是非公平锁顺序混乱。ReentrantLock默认非公平,可以设置为公平锁
3、锁可以绑定多个条件:synchronize只能通过wait和notify来同时绑定一个条件而ReentrantLock可以通过Condition来同时绑定多个条件

四、ThreadLocal
ThreadLocal解决的是同一个线程内的资源共享问题,而synchronized 解决的是多个线程间的资源共享问题
void set(T value)设置当前线程的线程局部变量的值。
public T get()该方法返回当前线程所对应的线程局部变量。
public void remove()将当前线程局部变量的值删除,目的是为了减少内存的占用,该方法是JDK 5.0新增的方法。需要指出的是,当线程结束后,对应该线程的局部变量将自动被垃圾回收,所以显式调用该方法清除线程的局部变量并不是必须的操作,但它可以加快内存回收的速度。
protected T initialValue()返回该线程局部变量的初始值,该方法是一个protected的方法,显然是为了让子类覆盖而设计的。这个方法是一个延迟调用方法,在线程第1次调用get()或set(T value)时才执行,并且仅执行1次。ThreadLocal中的缺省实现直接返回一个null。
五、Join的作用
若线程A调用B的Thread.Join(),那么A线程会暂停并等待B线程执行完毕
六、守护进程
当普通进程运行时守护进程可以运行,当普通进程停止时守护进程会被停止运行。实现方式是:setDaemon()
七、Volatile关键字
作用是每次读写的时候都在内存中进行强行的同步,但效率较低。他只保证可见性不能保证原子性。如果当前值与该变量以前的值相关,那么 volatile 关键字不起作用
八、synchronized关键字
访问同一个类的不同实例对象中的同步代码块,不存在阻塞等待获取对象锁的问题,因为它们获取的是各自 实例的对象级别锁,相互之间没有影响。
九、内存可见性
我们不仅希望防止某个线程正在使用对象状态而另一个线程在同时修改该状态,而且还希望确保当一个线程修改了 对象状态后,其他线程能够看到该变化
十、集合类的线程安全
对Vector和 HashTable来说是默认安全的,但其他集合类如ArrayList想要线程安全就必须通过Collections类进行转换 如下:
• public static Collection synchronizedCollention(Collection c)
• public static List synchronizedList(list l)
• public static Map synchronizedMap(Map m)
• public static Set synchronizedSet(Set s)
• public static SortedMap synchronizedSortedMap(SortedMap sm)
• public static SortedSet synchronizedSortedSet(SortedSet ss)
十一、死锁
当线程A持有锁A,线程B持有锁B。当线程A持有锁A时,需要访问线程B中锁B正在锁定的方法,同时线程B中持有的锁B也正在访问线程A中锁A持有的方法就会造成相互等待照成死锁。
遵循以下原则有助于规避死锁:
• 只在必要的最短时间内持有锁,考虑使用同步语句块代替整个同步方法;
• 尽量编写不在同一时刻需要持有多个锁的代码,如果不可避免,则确保线程持有第二个锁的时间尽量短暂;
• 创建和使用一个大锁来代替若干小锁,并把这个锁用于互斥,而不是用作单个对象的对象级别锁。
十二、wait() 方法和 notify()方法
wait() 方法:该方法用来将当前线程置入休眠状态,直到接到通知或被中断为止。在调用 wait()之前,线程必须要获得该对象 的对象级别锁,即只能在同步方法或同步块中调用 wait()方法。
notify()方法:该方法也要在同步方法或同步块中调用,即在调用前,线程也必须要获得该对象的对象级别锁。notify 后,当前线程不会马上释放该对象 锁,wait 所在的线程并不能马上获取该对象锁,要等到程序退出 synchronized 代码块后
notifyAll():该方法与 notify ()方法的工作方式相同,重要的一点差异是:
notifyAll 使所有原来在该对象上 wait 的线程统统退出 wait 的状态(即全部被唤醒,不再等待 notify 或 notifyAll,但由于此时还没有获取到该对象锁,因此还不能继续往下执行)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值