Could you recommend books on concurrent programming? I am self-learning concurrent programming. I have some experience with concurrent programming. Have self learned OS and programming. 

There are both programming languages and libraries that provide concurrent programming facilities. 
I would like to learn about concurrent programming  at OS and library levels (e.g. multithreading, multiprocessing, spin locks, semaphore, ...) and language level (e.g. monitor, future, promise, channels, conditional critical regions, Coroutine, ...). For the specific topics,  I am referring to sections "Models",   "Prevalence" and "Languages supporting concurrent programming" in https://en.wikipedia.org/wiki/Concurrent_computing and also concurrency patterns.

I would like to learn at conceptual as well as specific language levels.


Could you recommend some books which explain the different approaches at a concept level? It is good for such books to have  specific languages and libraries as examples, but not necessarily especially if the books you recommend are classic but not contemporary.
Could you also recommend which specific languages and libraries and books on specific languages and libraries? For specific languages, I am currently interested in functional languages (such as Scala, Haskell, OCaml ...), Python, C#, Java, C/C++ and Go.


Academic books (text books, survey) and professional/practical books are both welcome.
Concurrent programming is easy, synchronisation is hard.
Have a look at this video for an alternative to synchronisation: https://www.youtube.com/watch?v=2yXtZ8x7TXw
When you have to synchronize
Use easy (High level) synchronization. see:

Scoop from Eiffel.
Transactions
Pipelines / message passing
coroutines (for when you don't need parallelisation)

See also no lock / zero lock structures: Most pipes that are thread safe use locking. Or are not thread safe, and expect the user to do the locking. However it is possible to get thread safe zero lock queues. There rely on a few atomic instructions. (I prefer the name minimal lock, because the atomic instructions do locking).
Only use low-level synchronization to implement high-level synchronisation.
If you need synchronisation, and if you do not have high-level synchronisation, then find a good library that implements high-level synchronisation, using the existing low-level synchronisation.
Don't write it your self, except as an exercise (and do to it as an exercise, it is fun and you will learn a lot), as it is very hard and you will get it wrong.