并发: 就是CPU 在同一时刻执行多个任务.
java 的并发就是由多线程实现的. 但是使用多线程可能会引起 死锁,脏读等情况,会引起线程安全性问题.
线程安全就是:在多线程环境中,能永远保证程序的正确性.
从代码层面来说
我们一般要么使用 synchronized ,要么都是使用加锁的方式进行使用:
synchronized实现原理就是Java为每一个对象都内置了一个锁
对于一个类的普通方法来说,synchronized锁住的是每一个new出来的对象的方法,比如说对于如下代码:
public class Test{
public void synchronized testMethod()
{
.......
}
}
Test obj1 = new Test();
Test obj2 = new Test();
如果Thread-1 访问的是obj1,Thread-2访问的是obj2,那么两个线程都不会阻塞,因为这是两个不同的对象。
如果Thread-1 访问的是obj1,Thread-2访问的也是obj1,那么Thread-2会阻塞,因为两个线程访问的是同一个的对象,但是Thread-1先获取了锁,所以Thread-2必须等到Thread-1释放了锁,才能访问。
对于一个静态方法而言,synchronized则成为了一个类锁,对于上面所描述的场景,两种情况下,Thread-2都会被阻塞,因为静态方法是类的所有对象都共享的。
锁带啊吗块
Object obj = new Object();
public void method()
{
synchronized(obj)
{
....
}
.....
}
lock 与关键字的比较
举个例子:当有多个线程读写文件时,读操作和写操作会发生冲突现象,写操作和写操作会发生冲突现象,但是读操作和读操作不会发生冲突现象。
但是采用synchronized关键字来实现同步的话,就会导致一个问题:
如果多个线程都只是进行读操作,所以当一个线程在进行读操作时,其他线程只能等待无法进行读操作。
因此就需要一种机制来使得多个线程都只是进行读操作时,线程之间不会发生冲突,通过Lock就可以办到。
另外,通过Lock可以知道线程有没有成功获取到锁。这个是synchronized无法办到
采用synchronized不需要用户去手动释放锁,当synchronized方法或者synchronized代码块执行完之后,系统会自动让线程释放对锁的占用;而Lock则必须要用户去手动释放锁,如果没有主动释放锁,就有可能导致出现死锁现象。