关于线程安全,线程锁我们经常会用到,但你的使用姿势正确不,反正我用错了好长一段时间而不自知。所以有了这篇博客总结下线程锁的正确打开姿势 废话不说看例子 一,对整个方法进行加锁 1,对整个方法进行加锁,不同线程访问同一个类的同一个对象

public class TestRunnable implements Runnable {
@Override
public synchronized void run() {
// TODO Auto-generated method stub
for(int i=0;i<10;i++)
{
try {
Thread.sleep(200);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"---"+i);
}
}
}
public static void main(String[] args)
{
TestRunnable runnable=new TestRunnable();
Thread threadA=new Thread(runnable,"threadA");
threadA.start();
Thread threadB=new Thread(runnable,"threadB");
threadB.start();
}
运行结果: threadA—0
threadA—1
threadA—2
threadA—3
threadA—4
threadA—5
threadA—6
threadA—7
threadA—8
threadA—9
threadB—0
threadB—1
threadB—2
threadB—3
threadB—4
threadB—5
threadB—6
threadB—7
threadB—8
threadB—9

2,对整个方法进行加锁,不同线程访问同一个类的不同对象

public class TestRunnable implements Runnable {
@Override
public synchronized void run() {
// TODO Auto-generated method stub
for(int i=0;i<10;i++)
{
try {
Thread.sleep(200);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"---"+i);
}
}
}
public static void main(String[] args)
{
TestRunnable runnableA=new TestRunnable();
Thread threadA=new Thread(runnableA,"threadA");
threadA.start();
TestRunnable runnableB=new TestRunnable();
Thread threadB=new Thread(runnableB,"threadB");
threadB.start();
}

运行结果:

threadB—0
threadA—0
threadA—1
threadB—1
threadA—2
threadB—2
threadA—3
threadB—3
threadB—4
threadA—4
threadA—5
threadB—5
threadA—6
threadB—6
threadA—7
threadB—7
threadA—8
threadB—8
threadA—9
threadB—9

小结:对方法整体加锁的做法适用条件是 多个线程访问的必须是同一个类的同一个实例对象

一,对代码块进行加锁 1,对代码块进行加锁,加锁对象为当前类对象,不同线程访问同一个类的同一个对象

public class TestRunnable implements Runnable {
@Override
public void run() {
// TODO Auto-generated method stub
synchronized (TestRunnable.this) {
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "---" + i);
}
}
}
}
public static void main(String[] args)
{
TestRunnable runnable=new TestRunnable();
Thread threadA=new Thread(runnable,"threadA");
threadA.start();
Thread threadB=new Thread(runnable,"threadB");
threadB.start();
}

运行结果:

threadA—0
threadA—1
threadA—2
threadA—3
threadA—4
threadA—5
threadA—6
threadA—7
threadA—8
threadA—9
threadB—0
threadB—1
threadB—2
threadB—3
threadB—4
threadB—5
threadB—6
threadB—7
threadB—8
threadB—9

2,对代码块进行加锁,加锁对象为当前类对象,不同线程访问同一个类的不同对象

public class TestRunnable implements Runnable {
@Override
public void run() {
// TODO Auto-generated method stub
synchronized (TestRunnable.this) {
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "---" + i);
}
}
}
}
public static void main(String[] args)
{
TestRunnable runnableA=new TestRunnable();
Thread threadA=new Thread(runnableA,"threadA");
threadA.start();
TestRunnable runnableB=new TestRunnable();
Thread threadB=new Thread(runnableB,"threadB");
threadB.start();
}

运行结果:

threadB—0
threadA—0
threadB—1
threadA—1
threadB—2
threadA—2
threadA—3
threadB—3
threadA—4
threadB—4
threadB—5
threadA—5
threadA—6
threadB—6
threadB—7
threadA—7
threadA—8
threadB—8
threadA—9
threadB—9

3,对代码块进行加锁,加锁对象为当前类(不是类对象哦),不同线程访问同一个类的同一个对象

public class TestRunnable implements Runnable {
@Override
public void run() {
// TODO Auto-generated method stub
synchronized (TestRunnable.class) {
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "---" + i);
}
}
}
}
public static void main(String[] args)
{
TestRunnable runnable=new TestRunnable();
Thread threadA=new Thread(runnable,"threadA");
threadA.start();
Thread threadB=new Thread(runnable,"threadB");
threadB.start();
}

运行结果:

threadA—0
threadA—1
threadA—2
threadA—3
threadA—4
threadA—5
threadA—6
threadA—7
threadA—8
threadA—9
threadB—0
threadB—1
threadB—2
threadB—3
threadB—4
threadB—5
threadB—6
threadB—7
threadB—8
threadB—9

4,对代码块进行加锁,加锁对象为当前类(不是类对象哦),不同线程访问同一个类的不同对象

public class TestRunnable implements Runnable {
@Override
public void run() {
// TODO Auto-generated method stub
synchronized (TestRunnable.class) {
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "---" + i);
}
}
}
}
public static void main(String[] args)
{
TestRunnable runnableA=new TestRunnable();
Thread threadA=new Thread(runnableA,"threadA");
threadA.start();
TestRunnable runnableB=new TestRunnable();
Thread threadB=new Thread(runnableB,"threadB");
threadB.start();
}

运行结果:

threadA—0
threadA—1
threadA—2
threadA—3
threadA—4
threadA—5
threadA—6
threadA—7
threadA—8
threadA—9
threadB—0
threadB—1
threadB—2
threadB—3
threadB—4
threadB—5
threadB—6
threadB—7
threadB—8
threadB—9

5,对代码块进行加锁,加锁对象为已赋值的变量,不同线程访问同一个类的同一个对象

public class TestRunnable implements Runnable {
@Override
public void run() {
// TODO Auto-generated method stub
synchronized ("test") {
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "---" + i);
}
}
}
}
public static void main(String[] args)
{
TestRunnable runnable=new TestRunnable();
Thread threadA=new Thread(runnable,"threadA");
threadA.start();
Thread threadB=new Thread(runnable,"threadB");
threadB.start();
}

运行结果:

threadA—0
threadA—1
threadA—2
threadA—3
threadA—4
threadA—5
threadA—6
threadA—7
threadA—8
threadA—9
threadB—0
threadB—1
threadB—2
threadB—3
threadB—4
threadB—5
threadB—6
threadB—7
threadB—8
threadB—9

6,对代码块进行加锁,加锁对象为已赋值的变量,不同线程访问同一个类的不同对象

public class TestRunnable implements Runnable {
@Override
public void run() {
// TODO Auto-generated method stub
synchronized ("test") {
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "---" + i);
}
}
}
}
public static void main(String[] args)
{
TestRunnable runnableA=new TestRunnable();
Thread threadA=new Thread(runnableA,"threadA");
threadA.start();
TestRunnable runnableB=new TestRunnable();
Thread threadB=new Thread(runnableB,"threadB");
threadB.start();
}

运行结果:

threadA—0
threadA—1
threadA—2
threadA—3
threadA—4
threadA—5
threadA—6
threadA—7
threadA—8
threadA—9
threadB—0
threadB—1
threadB—2
threadB—3
threadB—4
threadB—5
threadB—6
threadB—7
threadB—8
threadB—9

小结:当对代码块进行加锁时,当加锁对象是一个确定值时(当前类,或者已赋值的变量) 不同线程访问同一个类的不同对象时也可以实现线程同步

最后奉上线程锁在实际开发中的应用—-单例模式

1,懒汉式写法

public class Singleton {
private static Singleton instance;
private Singleton (){}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}

2,懒汉式写法升级版(双重校验锁) 性能优于第一种

public class Singleton {
private static Singleton singleton;
private Singleton (){}
public static Singleton getSingleton() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}

3,饿汉式写法,不依赖于线程同步锁,依赖于静态变量和类的同步加载实现线程安全

public class Singleton {
private static Singleton instance = new Singleton();
private Singleton (){}
public static Singleton getInstance() {
return instance;
}
}