2024年网络安全最全聊一聊Kotlin中的线程安全,终局之战

还有兄弟不知道网络安全面试可以提前刷题吗?费时一周整理的160+网络安全面试题,金九银十,做网络安全面试里的显眼包!

王岚嵚工程师面试题(附答案),只能帮兄弟们到这儿了!如果你能答对70%,找一个安全工作,问题不大。

对于有1-3年工作经验,想要跳槽的朋友来说,也是很好的温习资料!

【完整版领取方式在文末!!】

93道网络安全面试题

内容实在太多,不一一截图了

黑客学习资源推荐

最后给大家分享一份全套的网络安全学习资料,给那些想学习 网络安全的小伙伴们一点帮助!

对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。

😝朋友们如果有需要的话,可以联系领取~

1️⃣零基础入门
① 学习路线

对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。

image

② 路线对应学习视频

同时每个成长路线对应的板块都有配套的视频提供:

image-20231025112050764

2️⃣视频配套工具&国内外网安书籍、文档
① 工具

② 视频

image1

③ 书籍

image2

资源较为敏感,未展示全面,需要的最下面获取

在这里插入图片描述在这里插入图片描述

② 简历模板

在这里插入图片描述

因篇幅有限,资料较为敏感仅展示部分资料,添加上方即可获取👆

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化资料的朋友,可以点击这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

1.2 kotlin中的synchronized使用

对方法加锁

对方法加锁的时候只需要加上@Synchronized 注解就Ok了,比如我们定义了以下方法:

@Synchronized
private fun postResult(s: String){
println(“ S y s t e m . c u r r e n t T i m e M i l l i s ( ) : {System.currentTimeMillis()} : System.currentTimeMillis()s” )
sleep(5000)
}

在不同的线程中调用该方法:

fun testFunSync() {
Thread{
postResult(“first thread”)
}.start()

Thread{
postResult(“second thread”)
}.start()
}

第一个线程调用postResult方法,输出当前时间后阻塞5s。5s之后第二个线程才能获取postResult 的锁。

输出结果:

1622794297695 ��first thread
1622794302698 ��second thread

输出结果和我们预想的一样,相差5s

如果我们将第一个线程进行阻塞呢,此时锁的获取情况是什么样的?

fun testFunSync() {
Thread{
postResult(“first thread”)
//我们在此线程阻塞10s,看下结果是否一样
sleep(10000)
}.start()

Thread{
postResult(“second thread”)
}.start()
}

1622794450105 ��first thread
1622794455107 ��second thread

输出结果依旧是一样的,first线程在执行玩postResult之后就会释放锁,后续的操作不会影响second线程获取postResult的锁


对类加锁

首先我们创建一个Result类:

class Result {

var s : String = “”

public fun printResult(){
println(“ S y s t e m . c u r r e n t T i m e M i l l i s ( ) : {System.currentTimeMillis()} : System.currentTimeMillis()s” )
Thread.sleep(5000)
}

}

调用

fun testClassSync() {
val result= Result()

Thread{
synchronized(result){
result.s = currentThread().name
result.printResult()
}
}.apply {
name = “first thread”
start()
}

Thread{
synchronized(result){
result.s = currentThread().name
result.printResult()
}
}.apply {
name = “second thread”
start()
}

}

输出结果:

1622795509253 ��first thread
1622795514269 ��second thread
//时间相差5s,说明锁生效了

以上就是对Result类对象加锁,如果Result类有多个实例对象怎么办?我们稍微修改下调用方法:

fun testClassSync() {
val result= Result()

//Result类的多个实例对象
val result2= Result()

Thread{
synchronized(result){
result.s = currentThread().name
result.printResult()
}
}.apply {
name = “first thread”
start()
}

Thread{
synchronized(result2){
result2.s = currentThread().name
result2.printResult()
}
}.apply {
name = “second thread”
start()
}

}

创建了多个Result类对象,first线程对A对象加锁,并不会影响second线程获取B对象锁,输出结果:

1622795623480 ��first thread
1622795623480 ��second thread

如果我们对Result类加锁,那所有的对象将会共享同一锁:

fun testClassSync() {
val result= Result()
val result2= Result()

//对Result类加锁
Thread{
synchronized(Result::class.java){
result.s = currentThread().name
result.printResult()
}
}.apply {
name = “first thread”
start()
}

Thread{
synchronized(Result::class.java){
result2.s = currentThread().name
result2.printResult()
}
}.apply {
name = “second thread”
start()
}

}

输出结果:

1622796124320 ��first thread
1622796129336 ��second thread

尽管first线程和second线程调用的是不同对象,但是first线程对Resutl类加上了类锁,second线程只能乖乖等着。

输出结果表示:对xx::class.java加上类锁的时候,该类所有的对象将会共享同一锁。


2.Lock

lock是一个接口,我们常用的实现类有ReentrantLock,意思是可重入锁。

我们定义一个全局变量,在两个线程中同时进行写操作,同时start两个线程

fun testLockSync() {

var count = 0

val thread1 = Thread{
for (i in 0…1000){
count += i
}
println(“ T h r e a d . c u r r e n t T h r e a d ( ) . n a m e : c o u n t : {Thread.currentThread().name} : count: Thread.currentThread().name:count:{count}”)
}

val thread2 = Thread{
for (i in 0…1000){
count += i
}
println(“ T h r e a d . c u r r e n t T h r e a d ( ) . n a m e : c o u n t : {Thread.currentThread().name} : count: Thread.currentThread().name:count:{count}”)
}

//同时开启两个线程
thread1.start()
thread2.start()
}

输出结果:会发现每次输出的结果都不一样

Thread-1 : count:505253
Thread-2 : count:1001000

Thread-2 : count:1001000
Thread-1 : count:1001000

Thread-2 : count:822155
Thread-1 : count:822155

使用ReentrantLock保证线程安全:

fun testLockSync() {

val lock = ReentrantLock()
var count = 0

val thread1 = Thread{
lock.lock()

for (i in 0…1000){
count += i
}
println(“ T h r e a d . c u r r e n t T h r e a d ( ) . n a m e : c o u n t : {Thread.currentThread().name} : count: Thread.currentThread().name:count:{count}”)

lock.unlock()
}

val thread2 = Thread{
lock.lock()

for (i in 0…1000){
count += i
}
println(“ T h r e a d . c u r r e n t T h r e a d ( ) . n a m e : c o u n t : {Thread.currentThread().name} : count: Thread.currentThread().name:count:{count}”)

lock.unlock()
}

thread1.start()
thread2.start()
}

输出结果和执行顺序每次都是一样:

Thread-1 : count:500500
Thread-2 : count:1001000

Lock常用方法

  • lock() :获取锁,获取成功设置当前线程count++,如果其他线程占有锁,则当前线程不可用,等待。
  • tryLock() : 获取锁,如果锁不可用,则此方法将立即返回,线程不阻塞,可设置等待时间。
  • unLock() : 尝试释放锁,当前thread count–,如果count为0,则释放锁。

2.Object

在kotlin中object有很多作用,可以实现对象表达式、对象声明等

对象表达式就是创建一个Object类,实现单例模式:

object Singleton {

}

在idea中查看其反编译java代码:

public final class Singleton {
public static final Singleton INSTANCE;

private Singleton() {
}

static {
Singleton var0 = new Singleton();
INSTANCE = var0;
}
}

可以看到其属于饿汉模式: 优点是在类加载的时候创建,不会存在线程安全问题,效率高。缺点就是浪费资源。具体可以参考此链接

但是在Object类中定义的方法并不是线程安全的

我们定义如下方法:

object Singleton {

fun printS(){
println(“${System.currentTimeMillis()} : T h r e a d . c u r r e n t T h r e a d ( ) . n a m e " ) s l e e p ( 1000 ) p r i n t l n ( " {Thread.currentThread().name}") sleep(1000) println(" Thread.currentThread().name")sleep(1000)println("{System.currentTimeMillis()} : ${Thread.currentThread().name}”)
}
}

调用:

fun testObjectSync() {

val thread1 = thread(start = false,name = “first thread”){
Singleton.printS()
}

val thread2 = thread(start = false,name = “second thread”){
Singleton.printS()
}

thread1.start()
thread2.start()
}

输出:

1623036691322 : first thread
1623036691322 : second thread
1623036692329 : second thread
1623036692329 : first thread

我们发现两个线程能够同时获取到对象,输出结果几乎是同一时间,并没有起到sleep效果。

还是需要加锁@Synchronized才能实现线程安全,如下:

object Singleton {

@Synchronized
fun printS(){
println(“${System.currentTimeMillis()} : T h r e a d . c u r r e n t T h r e a d ( ) . n a m e " ) s l e e p ( 1000 ) p r i n t l n ( " {Thread.currentThread().name}") sleep(1000) println(" Thread.currentThread().name")sleep(1000)println("{System.currentTimeMillis()} : ${Thread.currentThread().name}”)
}

}

输出:
1623036783474 : first thread
1623036784474 : first thread
1623036784474 : second thread
1623036785476 : second thread

3.by lazy实现

Object虽然非常简单是实现单例模式,但是Objcet不能初始化参数,我们可以利用by lazy 的延迟加载属性创建带参数的单例类:

class SomeSingleton(s:String) {

companion object{

private var s = “”

private val instance : SomeSingleton by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
SomeSingleton(s)
}

fun getInstances(string: String):SomeSingleton{
this.s = string
return instance
}
}

fun printS(){
println(“${System.currentTimeMillis()} : T h r e a d . c u r r e n t T h r e a d ( ) . n a m e − − − − − − − s i s : {Thread.currentThread().name} ------- s is: Thread.currentThread().namesis:{s}”)
Thread.sleep(5000)
}

}

注意这里的by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED)

延迟属性的在初始化的过程分多钟情况,首先是默认的SYNCHRONIZED,上锁为了保证只有一条线程可去初始化lazy属性。也就是说同时多线程进行访问该延迟属性时,如果没有初始化好,其他线程将无法访问。

延迟加载上锁实现源码:

学习路线:

这个方向初期比较容易入门一些,掌握一些基本技术,拿起各种现成的工具就可以开黑了。不过,要想从脚本小子变成黑客大神,这个方向越往后,需要学习和掌握的东西就会越来越多以下是网络渗透需要学习的内容:
在这里插入图片描述

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化资料的朋友,可以点击这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值